ES6新增了很多新特性,箭头函数、简化函数是我们接触的最多的特性了,但是它们与传统的Javascript函数(本文称之为普通函数)有些不同
一、箭头函数
- 没有this、super、arguments和new.target绑定
- 不能通过new关键字调用
- 没有原型
- 不可以改变this的绑定
- 不支持arguments对象
- 不支持重复的命名参数
- 不支持词法名称标识符
1. 没有this、super、arguments和new.target绑定
箭头函数中的this、super、arguments及new.target这些值由外围最近一层非箭头函数决定,它本身没有这些绑定,下面将用一些例子进行说明:
1.1、没有this绑定
var myObject = {
age:30,
run:()=>{
console.log('张三今年'+this.age+'岁');
}
}
myObject.run(); // 非严格模式下,打印出:张三今年undefined岁
var myObject2 = {
age:30,
run:function(){
setTimeout(()=>{
console.log('张三今年'+this.age+'岁')
},0)
}
}
myObject2.run(); // 张三今年30岁
上面第一个例子,直接在对象中定义了一个箭头函数方法,结果为undefiend,通过查找我们会发现,此时在非严格模式下的this指向了全局对象(window),第二个例子,我们在对象中定义了一个function函数,然后在函数里面使用了箭头函数,此时得到的结果是正常的,这说明箭头函数本身并没有this,this绑定由外层非箭头函数决定的,示例2等价于下面代码:
var myObject2 = {
age:30,
run:function(){
var that = this;
setTimeout(function(){
console.log('张三今年'+that.age+'岁');
},0)
}
}
myObject2.run(); // 张三今年30岁
1.2、没有super
var foo = {
run:()=>{
console.log(super.name);
}
}
var person = {
name:'张三'
}
Object.setPrototypeOf(foo,person);
foo.run(); // Uncaught SyntaxError: 'super' keyword unexpected here
1.3、没有arguments对象
var person = ()=>{
console.log(arguments[0]);
}
person(30); // Uncaught ReferenceError: arguments is not defined
1.4、没有new.target元属性
var person = ()=>{
console.log(new.target);
}
person(); // Uncaught SyntaxError: new.target expression is not allowed here
2、不能通过new关键字调用
箭头函数没有[[Construct]]方法,所以不能被用作构造函数,如果通过new关键字调用箭头函数,程序会抛出错误。
var Person = (age)=>{
this.age = age;
}
var obj = new Person(30); // Uncaught TypeError: Person is not a constructor
3、没有原型
由于不可以通过new关键字调用箭头函数,因而没有构建原型的需求,所以箭头函数不存在prototype这个属性。
var Person = (age)=>{
this.age = age;
}
console.log(Person.prototype); // undefined
4、不可以改变this的绑定
由于箭头函数没有自己的this,所以使用call/bind/apply等方法无法改变this的绑定
var obj = {
age:'唐华'
}
var foo = ()=>{
console.log(this.age);
}
foo.call(obj); // undefined
5、不支持arguments对象
箭头函数没有arguments绑定,所以只能通过命名参数或者不定参数(...)这两种形式访问函数的参数。
var foo = ()=>{
console.log(arguments[0]);
}
foo(10); // Uncaught ReferenceError: arguments is not defined
6、不支持重复的命名参数
无论在严格还是非严格模式下,箭头函数都不支持重复的命名参数。
var foo = (name,name)=>{
console.log(name,name);
}
foo(10,20); // Uncaught SyntaxError: Duplicate parameter name not allowed in this context
7、不支持词法名称标识符
箭头函数不能定义词法名称标识符,导致函数自我引用(递归、事件(解除)绑定)更难操作。
var Foo = {
// Uncaught SyntaxError: Malformed arrow function parameter list
bar:bar()=> {
console.log('箭头函数');
},
baz: function baz() {
console.log('普通函数');
}
};
二、简写函数
- super绑定
- 不支持词法名称标识符
1、super绑定
super关键字用于访问和调用一个对象的父对象上的函数。
class Person{
constructor(){
this.age = '30'
}
run(){
console.log(this.age)
}
}
class Foo extends Person{
constructor(){
super();
this.age = '40';
}
sayName(){
super.run();
}
}
var obj = new Foo();
obj.sayName();
上面的例子使用extends实现继承,在子类的constructor中必须调用super方法,因为子类没有自己的 this 对象,需要继承父类的this对象,子类中的super就代表了父类的构造函数,调用super(...)后子类中的this指向的是子类的实例,即super内部的this指的是Foo,相当于:Person.prototype.constructor.call(this)。
注意:super在静态方法之中指向父类,在普通方法之中指向父类的原型对象
2、不支持词法名称标识符
简写函数不能像普通函数一样定义词法名称标识符,导致函数自我引用(递归、事件(解除)绑定)更难操作。
var Foo = {
bar(){
console.log('简写函数');
},
baz: function baz() {
console.log('普通函数');
}
};
三、普通函数
- 没有super绑定
普通函数并没有super绑定,只有简写函数才有。
var foo = {
name:'tanghua'
}
var bar = {
run:function(){
console.log(super.name);
}
}
Object.setPrototypeOf(bar,foo);
bar.run(); // Uncaught SyntaxError: 'super' keyword unexpected here
上面的示例调用super关键字会抛出一个错误,因为super只能在简写函数中调用。