function wrap(func) {
console.log('0', this)
return function x() {
console.log('1', this)
func()
return function z() {
console.log('3', this)
}
}
}
var obj = {
x: 5,
test: wrap(function y() {
console.log('2', this)
})
}
obj.test()()
上面的代码记录
// 0 Window
// 1 Object
// 2 Window
// 3 Window
我很难理解是什么决定了this
的价值应该是什么。
// 0 Window
有意义的,因为这是第一次调用 wrap 的时间,此时不应将其值this
设置为 obj
// 1 Object
是有道理的obj.test
现在等于 function x()
,它正确地将this
记录为obj
// 2 Window
我不确定为什么会发生这种情况。为什么this
的值不会传播到func()
?我认为this
应该指的是函数的所有者。这是否意味着即使function y()
是在 obj 内部创建的,它也以某种方式被吊到窗户上?
// 3 Window
同样function z()
为什么this
的价值不是从function x()
传下来的。this
的价值不是应该在那里传播吗?
"this"绑定非常令人困惑。但是,如果您记住以下这些规则,则会更容易理解。根据Javascript文档,在这些顺序中,"this"绑定有四条规则:
- 新运算符
- 通过调用或应用方法显式或硬绑定
- 与包含对象的隐式绑定,如对象的方法
- 默认值(全局(
从脚本中,只有规则 #3 和 #4 适用,因为没有新的运算符和调用或应用方法。
所以解释是:
0 窗口 - 规则 #4 默认值(全局(
1 个对象 - 规则 #3 与包含对象的隐式绑定,就像对象的方法一样,obj.test 在你的例子中
2 窗口 - 规则 #4 默认值(全局(
3 窗口 - 规则 #4 默认值(全局(
接下来,本文最准确的指导,按顺序,函数调用脱糖
-
wrap.call(window, function() {})
-
obj.test.call(obj)
-
y.call(window)
-
z.call(window)
要记住的是,this
不会通过函数声明传播。this
的值完全取决于函数的调用方式。
我感到困惑的原因是因为我有点太习惯了箭头函数,它为你保留了this
的价值。
function wrap(func) {
return () => {
console.log(this)
return () => {
console.log(this)
func()
return () => console.log(this)
}
}
}
这种脱糖到
function wrap(func) {
var _this = this;
return function () {
console.log(_this);
return function () {
console.log(_this);
func()
return function () {
return console.log(_this);
};
};
};
}
并表明您必须显式传递this
的值。尽管即使使用箭头函数,但重要的是要注意对func
的调用不会保留this
的值。我需要做func.call(this)
才能做到这一点。