JavaScriptPing说前端三剑客

JavaScript之函数

2021-01-17  本文已影响0人  Ping开源

三、函数

目录:函数的定义和参数获取、变量的作用域 let const详解、方法的定义和参数的获取

1.函数的定义和参数获取

例:创建绝对值函数
1)定义函数
①定义方式一

function abs(x) {
  if(x>=0) {
    return x;
  } else {
    return -x;
  }
}

一旦1执行到return代表函数结束,返回结果。
如果没有执行到return,函数执行完也会返回结果,结果为undefined。
②定义方式二

var abs = function(x) {
  if(x>=0) {
    return x;
  } else {
    return -x;
  }
}

function(x){……}这是匿名函数,但是可以把结果赋值给abs。通过abs就可以调用函数,相当于Java的匿名内部类。
2)调用函数

abs(10)
abs(-10)

参数问题:JavaScript可以传任意个参数,也可以不传递参数。
参数进来是否存在的问题如何解决?
假设不存在参数如何规避?

var abs = function(x) {
  //手动抛出异常来判断
  if(typeof x!=='number') {
    throw 'Not a Number';
  }
  if(x>=0) {
    return x;
  } else {
    return -x;
  }
}

3)arguments
arguments是JS免费送的关键字,能获取传递进来的所有参数,是一个数组。

var abs = function(x) {
  console.log("x=>"+x);
  for(var i=0;i<arguments.length;i++) {
    console.log(arguments[i]);
  }
  if(x>=0) {
    return x;
  } else {
    return -x;
  }
}

问题:arguments包含所有的参数,有时候想使用多余的参数来进行附加操作,需要排除已有参数。
4)rest:ES6引入新特性,获取除了已经定义的参数之外的所有的参数。
以前

if(arguments.length>2) {//如果定义了2个参数
  for(var i=2;i<arguments.length;i++) {…}
}

现在

function f(a,b,…rest) {
  console.log("a=>"+a);
  console.log("b=>"+b);
  console.log(rest);
}

rest参数只能写在最后面,必须用…标识。有点像Java的可变长参数。

2.变量的作用域、let、const详解

1)在JavaScript中,var定义变量实际是有作用域的。
假设在函数体中声明,则在函数体外不可使用(非要想实现可以用闭包)。

function f() {
  var x=1;
}
x=x+2;//Uncaught ReferenceError: x is not defined

如果两个函数使用了相同的变量名,只要在函数内部就不冲突。

function f1() {
  var x=1;
}
function f2() {
  var x='A';
}

内部函数可以访问外部函数的成员,反之则不行。

function f() {
  var x=1;
  function f3() {
    var y=x+1;//2
  }
  var z=y+1;//Uncaught ReferenceError: y is not defined
}

假设内部函数变量和外部函数变量重名:

function f1() {
  var x=1;
  function f2() {
    var x='A'
    console.log('inner'+x);//innerA
  }
  console.log('outer'+x);//outer1
}

假设在JavaScript中函数查找变量从自身函数开始,由“内”向“外”查找,假设外部存在这个同名的函数变量,则内部函数会自动屏蔽外部函数的变量。
2)提升变量的作用域

function f() {
  var x="x"+y;
  console.log(x);
  var y="y";
}

结果为xundefined。
说明:js执行引擎,自动提升了y的声明,但是不会提升变量y的赋值。
上例等同于:

function f() {
  var y;
  var x="x"+y;
  console.log(x);
  y="y";
}

这个是在JavaScript建立之初就存在的特性。
规范:所有的变量定义都放在头部,不要乱发,便于代码维护。
3)全局变量
全局对象window

var x="xxx";
window.alert(window.x);//默认所有的全局变量,都会自动绑定在window对象下

alert()这个函数本身也是一个window变量。

var x="xxx";
window.alert(x);
var old_alert=window.alert;
//old_alert(x);
window.alert=function() {
};
window.alert(123);//123没有弹出,发现alert()失效了
//恢复
window.alert=old_alert;
window.alert(456);//弹出456

JavaScript实际上只有一个全局作用域,任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,报错RefrenceError。
4)规范

//唯一全局变量
var win={ }
//定义全局变量
win.name= "xiaoming";
win.add=function(a,b) {
  return a+b;
}

把代码全部放入定义的唯一空间名字中,降低全局命名冲突问题。
jQuery库把所定义的都放到jQuery中,并用简化符$()。
5)局部作用域let

function aa() {
  for(var i=0;i<100;i++) {
    console.log(i);
  }
  console.log(i+1);//101
}

问题:i出了这个作用域还可以使用。
ES6中let关键字,解决局部作用域冲突问题。

function aa() {
  for(let i=0;i<100;i++) {
    console.log(i);
  }
  console.log(i+1);//Uncaught ReferenceError: i is not defined
}

建议使用let去定义局部作用域的变量。
6)常量const
在ES6之前,怎么定义常量:只有用全部大写字母命名的变量就是常量,建议不要修改这样的值。

var PI='3.14';//可以改变这个值

在ES6引入了常量关键字const

const PI='3.14';
PI='123';//TypeError: Assignment to constant variable

3.方法的定义和参数获取

1)定义方法
方法就是把函数放在对象里面,对象只有两个东西,就是方法和属性。

var ming = {
  name: 'xiaoming',
  birth: 2001,
  //方法
  age: function() {
    var now = new Date().getFullYear();
    return now-this.birth;
  }
}
//调用属性
ming.name
//调用方法,一定要带()
ming.age()

this.代表什么?
拆开上面的代码来看。

var ming = {
  name: 'xiaoming',
  birth: 2001,
  //方法
  age: getAge
}
function getAge() {
    var now = new Date().getFullYear();
    return now-this.birth;
}
ming.age();//20
getAge();//NaN,单独使用,使用window对象,没有birth属性
}

this是无法指向的,是默认指向调用它的对象。
2)apply
在js中可以控制this指向。

getAge.apply(ming,[]);//this指向ming,参数为空。
上一篇 下一篇

猜你喜欢

热点阅读