题目A
let gg = this
let foo = function() {
console.log(this, gg);
let that = this
return function() {
for(let i = 0; i < 1; i++) {
console.log(this, that);
}
}
}
foo()()
题目B
let gg = this
let foo = function() {
console.log(this, gg);
let that = this
return () => {
for(let i = 0; i < 1; i++) {
console.log(this, that);
}
}
}
foo()()
题目AA
let gg = this
let foo = function() {
console.log(this, gg);
let that = this
return function() {
for(let i = 0; i < 1; i++) {
console.log(this, that);
}
}
}
foo = foo.bind({t:'t'})
foo()()
题目BB
let gg = this
let foo = function() {
console.log(this, gg);
let that = this
return () => {
for(let i = 0; i < 1; i++) {
console.log(this, that);
}
}
}
foo = foo.bind({t:'t'})
foo()()
试问,这4道题,在Node中、浏览器中的输出是多少?
如果能准确说出结果,恭喜你,你的闭包、变量作用域、箭头函数this等知识还挺牢固。
浏览器中
- 题目A:
window window
,window window
- 题目B:
window window
,window window
- 题目AA:
{t:'t'} window
,window {t:'t'}
- 题目BB:
{t:'t'} window
,{t:'t'} {t:'t'}
Node中
- 题目A:
global {}
,global global
- 题目B:
global {}
,global global
- 题目AA:
{t:'t'} {}
,global {t:'t'}
- 题目BB:
{t:'t'} {}
,{t:'t'} {t:'t'}
解释
- 谁调用的,this就指向谁
- 找不到谁调用的,this指向window/global
- 箭头函数为上一个作用域的this
初始作用域
- 浏览器在执行脚本时的初始作用域(Script)的this为
window
- Node在执行文件时,会使用包装器函数包装一层以提供
module require exports等等
,该函数的this为{}
总的来说
浏览器会有以下形式的作用域链
window Script(初始域this为window) Closure*(闭包链) Local(当前函数域) Block(for中let形成的域)
当以module方式引入时
window Module(初始域this为undefined) Closure*(闭包链) Local(当前函数域) Block(for中let形成的域)
Node会有以下作用域链
global Closure(初始域this为{}) Closure*(闭包链) Local(当前函数域) Block(for中let形成的域)
附加题P
let gg = this
let foo = function() {
console.log(this, gg);
let that = this
return function() {
for(let i = 0; i < 1; i++) {
console.log(this, that);
}
}
}
foo = foo.bind({t:'t'})
foo().bind({x:'x'})()
附加题PP
let gg = this
let foo = function() {
console.log(this, gg);
let that = this
return () => {
for(let i = 0; i < 1; i++) {
console.log(this, that);
}
}
}
foo = foo.bind({t:'t'})
foo().bind({x:'x'})()
以上两个解释了箭头函数和普通函数的区别,普通函数会找谁调用的它,而箭头函数会找上一层作用域中的this,所以在node中P的结果为{t:'t'} {}
, {x:'x'} {t:'t'}
,PP的结果为{t:'t'} {}, {t:'t'} {t:'t'}
.
bind做了什么
对比原函数,我们可以看到添加了[[BoundThis]]和[[BoundArgs]]
两个属性,从而替换this
vue2中实例的函数
同样可以看到,vue2对methods中的函数绑定了this,所以当组件间传递函数时,函数执行时其中的this仍是原组件实例。