简要概述this
this
在 JavaScript 中是动态作用域的。它的行为不同于所有其他词法范围的变量。其他变量没有不同的绑定,具体取决于函数的调用方式;它们的范围来自它们在脚本中出现的位置。this
但是行为不同,并且可以具有不同的绑定,这取决于它在脚本中出现的位置,而取决于它的调用方式。因此,对于学习这门语言的人来说,它可能是一个困惑的根源,但要成为一名熟练的 JavaScript 开发人员,掌握它是必要的。
由于this
是动态绑定的,因此有多种方法可以根据您调用函数的方式更改其值。
例子
在 JavaScript 中执行函数时,默认this
值为window
.
function foo() {
console.log(this);
}
foo(); // => window
this
可以通过多种方式更改该值。一种方法是将函数作为对象的方法调用:
var x = {
foo: function() {
console.log(this);
}
};
x.foo(); // => This time it's the x object.
另一种方法是使用call
或apply
告诉函数在某个对象的上下文中执行。
function foo() {
console.log(this);
}
foo.call(x); // => x object again
foo.apply(x); // => x object as well
如果你call
或apply
在null
或undefined
,默认行为将再次发生:该函数将在上下文中执行window
:
function foo() {
console.log(this);
}
foo.call(null); // => window
foo.apply(undefined); // => window
但是,请注意,在 ECMAScript 5严格模式下,this
不默认为窗口:
(function() {
'use strict';
function foo() {
console.log(this);
}
foo(); // => undefined
foo.call(null); // => null
foo.apply(undefined); // => undefined
})();
您还可以在调用函数之前将其设置为this
将bind
函数绑定到对象:
function foo() {
console.log(this);
}
var bar = {
baz: 'some property'
};
var foobar = foo.bind(bar);
foobar(); // => calls foo with bar as this
成为父亲:懒惰的绑定/ Uncurryingthis
更进一步,您有时可能希望采用作用于 athis
并允许将this
值作为函数的第一个参数传入的函数。这对于 Array 方法非常有用,例如forEach
. 例如,假设您正在处理一个类似数组但实际上不是数组的对象。
var arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
'length': 3
};
如果你想用 迭代这个对象forEach
,你可以使用call
:
Array.prototype.forEach.call(arrayLike, function(item) {
console.log(item);
});
// Logs: a, b, c
但是,另一种选择是创建一个forEach
可以直接在您的对象上调用的函数:
var forEach = Function.prototype.call.bind(Array.prototype.forEach);
现在,您可以在任何时候想要迭代类似数组的对象时使用此函数:
forEach(arrayLike, function(item) {
console.log(item);
});
// Logs: a, b, c
有时这种方法被称为“uncurrying this
”。但是,我更喜欢创建一个可以生成这些“非curried”函数并将其称为“惰性绑定”的函数。
var lazyBind = Function.prototype.bind.bind(Function.prototype.call);
var forEach = lazyBind(Array.prototype.forEach);
var slice = lazyBind(Array.prototype.slice);
var map = lazyBind(Array.prototype.map);
forEach(arrayLike, function(u) {
console.log(u);
});
// Logs: a, b, c
var realArray = slice(arrayLike);
// Converts arrayLike into a real array
forEach(
map(arrayLike, function(u) {
return u + 'Q';
}),
function(u) {
console.log(u);
}
);
// Logs: aQ, bQ, cQ
关于这种技术的一个非常棒的事情是它可以用于创建安全的 JavaScript,如果您不希望页面上的其他脚本窥探您的内部变量,这将很有帮助。不过,这是一种非常先进的元编程技术,您在日常 JavaScript 中看不到它。