function abs(x){}
如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefined
var 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; // 保存原函数
window.parseInt = function () {
count += 1;
return oldParseInt.apply(null, arguments); // 调用原函数
};
八、闭包
高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
1️⃣ 结构体:
function lazy_sum(arr) {
var sum = function () {
return arr.reduce(function (x, y) {
return x + y;
});
}
return sum;
}
在函数lazy_sum中又定义了函数sum:
内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中。
2️⃣ 返回的函数并不会立刻执行,而是直到调用了f()才执行
//返回函数引用循环变量:返回函数结果都相同-变量相同
function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push(function () {
return i * i;
});
}
return arr;
}
一定要引用循环变量:再创建一个函数,用该函数的参数绑定循环变量当前的值
function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push((function (n) {
return function () {
return n * n;
}
})(i));
}
return arr;
}
3️⃣ 这里用了一个“创建一个匿名函数并立刻执行”的语法
(function (x) {
return x * x;
})(3); // 9
由于JavaScript语法解析的问题,会报SyntaxError错误,因此需要用括号把整个函数定义括起来(function (x) { return x * x }) (3);
4️⃣ 功能
闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来应用:封装一个私有变量
//用JavaScript创建一个计数器
function create_counter(initial) {
var x = initial || 0;
return {
inc: function () {
x += 1;
return x;
}
}
}
var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3
var c2 = create_counter(10);
c2.inc(); // 11
c2.inc(); // 12
c2.inc(); // 13
把多参数的函数变成单参数的函数
//利用闭包创建新的函数pow2和pow3
function make_pow(n) {
return function (x) {
return Math.pow(x, n);
}
}
// 创建两个新函数:
var pow2 = make_pow(2);
var pow3 = make_pow(3);
console.log(pow2(5)); // 25
console.log(pow3(7)); // 343
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)