1.块级函数
(在if里面声明函数,会不会变量提升?有let就不会提升,function Name(){}就会被提升;
会提升到哪里?es6会提升到全局,其他情况会提升到if顶部)
2.箭头函数 *
调用函数表达式 IIFE
没有 this 绑定
箭头函数与数组
没有 arguments 绑定
识别箭头函数
块级函数
ES5(严格模式)不允许 在代码块中声明函数(即块级函数),像这样:
"use strict";
if (true) {
function doSomething() { } // 在 ES5 会抛出语法错误, ES6 则不会
}
ES6 则不会,
ES6 会将 doSomething() 函数视为块级声明, 并允许它在定义所在的代码块内部被访问。
"use strict";
if (true) {
console.log(typeof doSomething); // "function" // 变量提升
function doSomething() {}
doSomething();
}
console.log(typeof doSomething); // "undefined"
决定何时使用块级函数
块级函数与 let 函数表达式相似,在执行流跳出定义所在的代码块之后,函数定义就会被移 除。
关键区别在于:块级函数会被提升到所在代码块的顶部;而使用let 的函数表达式则不 会,
var getName = function() {
console.log(typeof name); // 错误
let name = 'Sam';
console.log(typeof name); // string
console.log(typeof sayName); // 错误
let sayName = function() {
console.log('sayName');
}
console.log(typeof sayName); // function
console.log(typeof backName); // function
function backName() {
return 'backName';
}
console.log(typeof backName); // function
}
getName();
非严格模式的块级函数
ES6非严格模式
// ES6 behavior
if (true) {
console.log(typeof doSomething); // function
function doSomething() {}
doSomething();
}
console.log(typeof doSomething); // function
块级函数的作用域会被提 升到所在函数或全局环境的顶部,而不是代码块的顶部。
箭头函数
使用一个“箭头”( => )来定义.
与传统的 JS 函数的区别:
没有 this 、 super 、 arguments ,也没有new.target 绑定: this 、 super 、 arguments 、以及函数内部的new.target 的值由所在的、最靠近的非箭头函数来决定
不能被使用 new 调用: 箭头函数没有 [[Construct]] 方法,因此不能被用为构造函 数,使用new 调用箭头函数会抛出错误。
没有原型: 既然不能对箭头函数使用 new ,那么它也不需要原型,也就是没有prototype 属性。
不能更改 this : this 的值在函数内部不能被修改,在函数的整个生命周期内其值会 保持不变。
没有 arguments 对象: 既然箭头函数没有 arguments 绑定,你必须依赖于具名参数或 剩余参数来访问函数的参数。
不允许重复的具名参数:箭头函数不允许拥有重复的具名参数,无论是否在严格模式 下;而相对来说,传统函数只有在严格模式下才禁止这种重复。
但是:箭头函数也拥有 name 属性,并且遵循与其他函数相同的规则.
如果没有参数:
var reflect = _ => 'this is returnTxt';
var reflect = function() {
return 'this is returnTxt';
}
如果是一个参数:
var reflect = value => value;
var reflect = function(value) {
return value;
};
如果是多个参数:
var reflect = (num1, num2) => num1 + num2;
var reflect = function(num1, num2) {
return num1 + num2;
}
如果函数体内容较多,也可使用{ return…}
var reflect = (a, b) => {
return a + b;
}
var reflect = function(a, b) {
return a + b;
}
如果没有函数体的空函数:
var reflect = () => {}
var reflect = function() {}
如果 返回一个对象字面量:
var getTempItem = (id) => ({ id: id, name: 'Temp'});
var getTempItem = function(id) {
return {
id,
name: 'Temp'
}
}
注意:箭头函数返回对象是用()圆括号括起来的.
标示了括号内是一个字面量而不是函数体.
## 创建立即调用函数表达式(IIFE)
IIFE 允许你定义一个匿名函数并在未保存引用的情况下立刻调用它。
当你想创建一个作用域并隔离在程序其他部分外,这种模式就很有用了。
// 匿名函数立即执行IIFE
let person = function(name) {
return {
getName: function() {
return name;
}
};
}("Nicholas");
console.log(person.getName()); // Nicholas
// 箭头函数立即执行IIFE
let person = ((name) => {
return {
getName: function() {
return name;
}
};
})("Nicholas");
console.log(person.getName()); // Nicholas
注意箭头函数的括号,只包括了函数的定义.
// 传统一般函数
(function() {})()
(function() {} ())
// 箭头函数
(() => {})()
没有 this 绑定
常见bug函数内的 this 绑定
由于一个函数内部的 this 值可以 被改变,这取决于调用该函数时的上下文,
因此完全可能错误地影响了一个对象,尽管你本 意是要修改另一个对象.
var PageHandler = {
id: "123456",
init: function() {
document.addEventListener("click", function(event) {
console.log(this);
// this.doSomething(event.type); // 错误
// 此处的this指的是document.而不是PgeHandler
}, false);
},
doSomething: function(type) {
console.log("Handling " + type + " for " + this.id);
}
};
PageHandler.init();
// 解决方案
// 使用bing方法,将函数的this绑定到PageHandler
var PageHandler0 = {
id: "123456",
init: function() {
document.addEventListener("click", (function(event) {
console.log(this);
// this.doSomething(event.type); // 没有错误
}).bind(this), false);
},
doSomething: function(type) {
console.log("Handling " + type + " for " + this.id);
}
};
PageHandler0.init();
// 调用 bind(this) ,你实际上创建 了一个新函数,
// 它的 this 被绑定到当前 this (也就是 PageHandler )上。
// 因此,建议使用箭头函数
var PageHandler1 = {
id: "123456",
init: function() {
document.addEventListener("click",
event => this.doSomething(event.type), false);
},
doSomething: function(type) {
console.log("Handling " + type + " for " + this.id);
}
};
由于箭头函数的 this 值由包含它的函数决定,因此不能使用call() 、 apply() 或 bind() 方法来改变其 this 值。
箭头函数与数组
var result = values.sort(function(a, b) {
return a - b;
});
var result = values.sort((a, b) => a - b);
就是简化代码
没有 arguments 绑定
尽管箭头函数没有自己的 arguments 对象,但仍然能访问包含它的函数的 arguments 对 象。无论此后箭头函数在何处执行,该对象都是可用的。
function createArrowFunctionReturningFirstArg() {
return () => arguments[0];
}
var arrowFunction = createArrowFunctionReturningFirstArg(5);
console.log(arrowFunction()); // 5
识别箭头函数
var comparator = (a, b) => a - b;
console.log(typeof comparator);
console.log(comparator instanceof Function);
可以对箭头函数使用 call() 、 apply() 与 bind() 方法,
虽然函数的 this 绑定并不会受影响。
var sum = (num1, num2) => num1 + num2;
console.log(sum.call(null, 1, 2)); // 3
console.log(sum.apply(null, [1, 2])); // 3
var boundSum = sum.bind(null, 1, 2);
console.log(boundSum()); // 3
网友评论