一、定义
function abs(x){}
如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefinedvar abs = function (x) {};
注意第二种方式按照完整语法需要在函数体末尾加一个" ; ",表示赋值语句结束
由于JavaScript的函数也是一个对象
上述定义的abs()函数实际上是一个函数对象,而函数名abs可以视为指向该函数的变量 (1,2完全等价)
调用:JavaScript允许传入任意个参数而不影响调用
二、 关键字arguments
关键字arguments只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。
arguments类似Array但它不是一个Array
function foo(x) {
console.log('x = ' + x); // 10
for (var i=0; i<arguments.length; i++) {
console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30
}
}
foo(10, 20, 30);
arguments最常用于判断传入参数的个数
三、rest参数(ES6新增)
function foo(a, b, ...rest){}
传入的参数先绑定a、b,多余的参数以数组形式交给变量rest。
所以,不再需要arguments我们就获取了全部参数。
四、变量提升
函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部
【 JavaScript引擎自动提升变量的声明,但不会提升变量的赋值 】
(由于JavaScript的这一怪异的“特性”,我们在函数内部定义变量时,请严格遵守“在函数内部首先申明所有变量”这一规则)
五、作用域
-
全局作用域
JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性 (顶层函数的定义也被视为一个全局变量)任何变量(函数也视为变量),如果没有在当前函数作用域中找到,就会继续往上查找,最后如果在全局作用域中也没有找到,则报ReferenceError错误
名字空间:
减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中。
许多著名的JavaScript库都是这么干的:jQuery,YUI,underscore等等。
-
局部作用域
为了解决块级作用域,ES6引入了新的关键字let,用let替代var可以申明一个块级作用域的变量引入了新的关键字const定义常量,const与let都具有块级作用域
六、解构赋值 (ES6新增)
-
同时对一组变量进行赋值
var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];
// 忽略前两个元素,只对z赋值第三个元素
let [, , z] = ['hello', 'JavaScript', 'ES6'];
-
//从对象中取出若干属性 (分别被赋值为person中对应变量名的属性):
var {name, age, passport} = person;
//嵌套取值
var {name, address: {city, zipcode}} = person;
//要使变量名和属性名不一致
// 把passport属性赋值给变量id:
let {name, passport:id} = person;
(如果对应的属性不存在,变量将被赋值为undefined)
-
//使用默认值
// 如果person对象没有single属性,默认赋值为true:
var {name, single=true} = person;
-
语法错误:
// 声明变量: var x, y; // 解构赋值: { x, y} = { name: '小明', x: 100, y: 200}; // 语法错误: Uncaught SyntaxError: Unexpected token =
这是因为JavaScript引擎把{开头的语句当作了块处理,于是=不再合法。解决方法是用小括号括起来:
({ x, y} = { name: '小明', x: 100, y: 200});
七、this
在一个方法内部,this始终指向当前对象
=> 要保证this指向正确,必须用obj.xxx()的形式调用。单独调用函数,this指向全局对象。
=> ECMA决定,在strict模式下让函数的this指向undefined (在非strict模式下,指向全局对象window)
1️⃣ 解决方法:
用 var that = this;
首先捕获this,就可以放心地在方法内部定义其他函数,而不是把所有语句都堆到一个方法中。
2️⃣ 控制this指向:
- apply
要指定函数的this指向哪个对象,可以用函数本身的apply方法。
它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空
- call
另一个与apply()类似的方法是call(),唯一区别是:
apply()把参数打包成Array再传入;
call()把参数按顺序传入。
对普通函数调用,我们通常把this绑定为null
Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5
3️⃣ 装饰器:
利用apply(),还可以动态改变函数的行为
// 修改默认函数:
var count = 0;
var oldParseInt = parseInt;