Mik*_*378 4 javascript function this ecmascript-5
关于这段代码:
var name = "Jaguar";
var car = {
name:"Ferrari",
getName:function(){
return this.name;
}
};
alert((car.getName = car.getName)());
Run Code Online (Sandbox Code Playgroud)
输出是:Jaguar.
为什么this对象对应Window于car变量中包含的对象而不是对象?
似乎将对象的函数重新分配给自身的事实导致在this调用函数时丢失对象的赋值...
我试图猜测:它是否存在一种机制(使用变量或其他),密切关注对象函数的非重新配置,以便在发生这种情况时,这种机制会阻止this关键字的分配.平常(因为等于对象)?
原因相当微妙:thisJavaScript完全取决于函数的调用方式.要在调用期间this设置为,您必须在从对象中检索它时立即调用,如下所示:cargetNamegetNamecar
car.getName() // or
car["getName"]()
Run Code Online (Sandbox Code Playgroud)
(或通过Function#call或Function#apply,它允许您明确指定值this.)
你在你的例子中做的是这样的:
// Set f to the result of the assignment expression,
// which is a reference to the getName function
var f = (car.getName = car.getName);
// Call it (separately)
f();
Run Code Online (Sandbox Code Playgroud)
......这是不同的.以这种方式调用的函数将this设置为全局对象(window在浏览器中).(除了在严格模式;在严格模式this将是undefined).
更多(来自我的贫血博客):
是否存在一种机制(使用变量或其他)密切关注对象函数的非重新分配,以便在发生这种情况时,这种机制会像往常一样阻止对该关键字的分配(因为它等于物体)?
我不完全确定我会遵循这个问题,但是如果你想拥有一个总是有预设this值的函数,那么是的,有几种方法可以做到这一点.
一种是使用新的ES5功能bind:
var name = "Jaguar";
var car = {
name: "Ferrari"
};
car.getName = function(){
return this.name;
}.bind(car);
alert((car.getName = car.getName)()); // "Ferrari"
Run Code Online (Sandbox Code Playgroud)
bind返回一个始终this设置为您给出的参数的函数.
另一种方法是使用闭包.事实上,您可以bind非常轻松地在ES3中创建类似函数:
function pseudoBind(func, thisArg) {
return function() {
return func.apply(thisArg, arguments);
};
}
Run Code Online (Sandbox Code Playgroud)
这并不能做到一切bind,但它确实起到了this作用.那你就得:
var name = "Jaguar";
var car = {
name: "Ferrari"
};
car.getName = pseudoBind(function(){
return this.name;
}, car);
alert((car.getName = car.getName)()); // "Ferrari"
Run Code Online (Sandbox Code Playgroud)
关于闭包的更多信息(再次来自博客):
在未来的规范中,我们将获得一种声明式方法来创建具有预设this值的函数(所谓的" 箭头函数 ",因为它们的语法涉及使用=>而不是function关键字).
Aaah,this决议......让我们看一眼.
var toy = {
log : function () { console.log(this); }
};
toy.log() //logs the toy object
Run Code Online (Sandbox Code Playgroud)
到目前为止,似乎this解决方案是静态的:无论在何处定义方法,这都是它的this价值.
但!如果我们这样做会怎样
var sneakyBastard = toy.log;
sneakyBastard(); //logs Window
Run Code Online (Sandbox Code Playgroud)
this绑定到它所调用的对象.在这种情况下toy.log,您log在toy对象的上下文中调用.但是,sneakyBastard没有固定的背景,所以就像你打电话一样window.sneakyBastard.
现在让我们在你的表情上拿一只鹅(鹅?鹅?不......)
(car.getName = car.getName)()
Run Code Online (Sandbox Code Playgroud)
......什么是作业归还?指定值,在本例中为函数,car.getName.我们可以将这个表达式分为两个:
var returnedValue = (car.getName = car.getName);
returnedValue();
Run Code Online (Sandbox Code Playgroud)
......而且从这里来看很明显.