前言
再掌握this之前掌握执行上下文环境对this的理解会事半功倍
执行上下文
作用域
function fun() {
return () => {
return () => {
return () => {
console.log(this.name)
}
}
}
}
var f = fun.call({ name: 'foo' })
var t1 = f.call({ name: 'bar' })()()
var t2 = f().call({ name: 'baz' })()
var t3 = f()().call({ name: 'qux' })
// foo foo foo,箭头函数没有自己的this绑定无效,默认都会向外层找,
console.log("==========")
function fun1() {
return function() {
return function() {
return function() {
console.log(this)
}
}
}
}
var tf = fun1.call({ name: 'foo' })
tf()()()
var tt1 = tf.call({ name: 'bar' })()()
var tt2 = tf().call({ name: 'baz' })()
var tt3 = tf()().call({ name: 'qux' })
console.log("=======")
// window window window {name:'qux'}
function fun2() {
return function() {
return () =>{
return ()=> {
console.log(this)
}
}
}
}
var ttf = fun2.call({ name: 'foo' })
var ttt1 = ttf.call({ name: 'bar' })()()
var ttt2 = ttf().call({ name: 'baz' })()
var ttt3 = ttf()().call({ name: 'qux' })
// {name:'bar'} window window(这两个输出一个空行)
普通函数中的this
这是一道面试题,
先思考一下即可,带着疑问看下面的例子就知道应该输出什么了。
先通过代码来更清除的解释
function test() {
console.log(this)
console.log(this.a)
}
let per = {
a :1,
fun:test
}
var a = 6//这里不要用let,var默认添加到windows对象中,后面好对比
test() //Window {parent: Window, opener: null,a:6 …} 6
console.log('######')
console.log(this)//查看最外层的上下文环境
per.fun() //{a: 1, fun: ƒ} 1
先说结论:普通函数this指的是函数执行是所在的上下文环境,而箭头函数是定义时的上下文环境中的this
先有个概念就可以,接着看下面就理解了。首先定义一个函数,这个不需要说明,然后定义一个对象其中包含两个属性。调用test方法的时候,函数函数打印出的结果说明:test函数的执行环境是在windows对象环境下执行的,该环境下包含属性a(也就是this.a),属性值为6,所以输出是6。
对应per.fun() :函数执行的时候是由per调用,执行的上下文是per,所以输出a为1,上下文是per对象
函数定义好之后,可以在不同的上下文环境下执行
看下面的图帮助理解(首先可以打印查看一下代码执行环境(console.log(this)里面包含函数fun和a,也就证明函数和变量在windows对象中)
再看箭头函数和普通函数的对比
let person = {
a : 3,
b : 10,
eat : ()=>{
console.log("eat-->this:",this)
console.log("eat",this.a)
},
drink :function () {
console.log("drink-->this:",this)
console.log("drink",this.b)
},
speak :()=>{
console.log("speak->this one",this)
let say = function () {
console.log("speak->this",this)
}
say()
},
walk :function () {
console.log("walk->this one",this)
let foot = ()=> {
console.log("walk->this",this)
}
foot()
},
sleep:function () {
console.log("sleep-->this one",this)
let f = function() {
console.log("sleep-->this",this)
}
f()
}
}
person.eat()
/*
eat-->this: Window
eat undefined
*/
person.drink()
/*
drink-->this: {a: 3, b: 10, eat: ƒ, drink: ƒ, speak: ƒ, …}
drink 10
*/
person.speak()
/*
speak->this one Window {parent: Window, opener: null, …}
speak->this Window {parent: Window, opener: null, …}
*/
person.walk()
/*
walk->this one {a: 3, b: 10, eat: ƒ, drink: ƒ, speak: ƒ, …}
walk->this {a: 3, b: 10, eat: ƒ, drink: ƒ, speak: ƒ, …}
*/
person.sleep()
/*
sleep-->this one {a: 3, b: 10, eat: ƒ, drink: ƒ, speak: ƒ, …}
sleep-->this Window
*/
箭头函数this是使用的外层的this,定义箭头函数时外层this是window,没有自己的this,所以eat中的this是在window对象层。其他的类似。