普通函数和箭头函数
注:例子建立在非严格模式下,新版chrome浏览器下
严格模式下:window是undefined
node下:window是global
网上有很多理解,这里写下我的理解法
最大的区别:
普通函数:this指向它的上级宿主对象(没有就指向window)
箭头函数:本身没有this,是从直接调用者(主要是向上找上级函数作用域)上面继承下来的,如果没有,就指向全局作用域window
举几个例子
//sayA函数没有宿主对象,this就是指向window,window.name = undefined
const sayA = function(){
const name = 'hc';
console.log(this.name+' say');
}
sayA();//undefined say 等价于window.sayA();
//没有sayB的直接调用者,就是指向window
const sayB = () => {
const name = 'hc';
console.log(this.name+' say');
}
sayB();//undefined say
const objA = {
name : 'hc',
say: function() {
console.log(this.name+' say');
}
}
//say的宿主对象是objA,所以this指向obj
objA.say();//hc say
const objB = {
name : 'hc',
say: () => {
console.log(this.name+' say');
}
}
//没有say的直接调用者(注意这里的objB不属于它的直接调用者),所以指向window
objB.say();//undefined say
//还有一种写法是这样的,和objA和objB其实是一样的
const obj = {
name: 'hc'
}
const fnSay = function(){
console.log(this.name+' say');
}
const fnSay = () => {
console.log(this.name+' say');
}
fnSay.call(obj);//等价于objA,objB的结果
const objC = {
name: 'hc',
say: function(){
console.log(this.name+' say');
return function(){
console.log(this.name+' repeat');
}
}
}
//say函数的宿主对象是objC,所以this = objC,
//say底下的function上级宿主对象没有,所以this = window
objC.say()();
//hc say
//undefined repeat
const objD = {
name: 'hc',
say: function(){
console.log(this.name+' say');
return () => {
console.log(this.name+' repeat');
}
}
}
//say函数的宿主对象是objC,所以this = objC,底下的()=>,
//向上找函数作用域,是say function所在的作用域,所以直接调用者是objC
objD.say()();
//hc say
//hc repeat
window.a = 'daxian';
const objE = {
a: 'hc',
run: function(){
return {
b: this.a + ' run',
runDown: () => {
console.log(this.a+ ' runDown');
console.log(this.b+ ' runDown');
return function(){
console.log(this.a+ ' runDeep');
console.log(this.b+ ' runDeep');
}
}
}
},
walk: () => {
return {
b: this.a+ ' walk',
walkSlow: function() {
console.log(this.a+ ' walkSlow');
console.log(this.b+ ' walkSlow');
},
walkFast: () => {
console.log(this.a+ ' walkFast');
console.log(this.b+ ' walkFast');
}
}
}
}
objE.run().runDown()();
objE.walk().walkSlow();
objE.walk().walkFast();
// hc runDown
// undefined runDown
// daxian runDeep
// undefined runDeep
// undefined walkSlow
// daxian walk walkSlow
// daxian walkFast
// undefined walkFast
objE的例子分解一下
objectE.run().runDown()();
- .run()普通函数:上级宿主对象的是objectE,所以返回一个新对象时候,b属性的this.a是指objectE底下的a,为’hc’,所以此时的b为this.a+’ run’为’hc run’
- .runDown()箭头函数:向上找函数作用域,它的上级函数作用域是run函数,所以对应的直接调用者是objectE,所以此时的this.a为 ‘hc’,objectE底下的b属性没定义,所以this.b为undefined。
- runDown底下的()普通函数:上级宿主对象没有,所以this指向window,window的a属性为’daxian’,b属性没定义,所以this.a = ‘daxian’,this.b=undefined
objectE.walk().walkSlow();
- .walk()箭头函数:向上找函数作用域,没有,则直接调用者是window,返回一个新对象的时候,b属性的this.a为window.a,this.a+‘ work’为’daxian work’
- .walkSlow()普通函数:上级宿主对象为.walk()返回的那个对象,所以this.a为undefined,this.b为’daxian work’。
objectE.walk().walkFast();
- .walk()箭头函数:原理已写。
- .walkFast()箭头函数:向上找函数作用域,没有,则直接调用者是window,因为window.a=‘daxian’,所以this.a+‘ walkFast’为’daxian walkFast’,window.b没定义为undefined,this.b+’ walkFast’为’undefined walkFast’
下一章
普通函数this指向进阶实例讲解