"this"对象的奇怪值

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对象对应Windowcar变量中包含的对象而不是对象?

似乎将对象的函数重新分配给自身的事实导致在this调用函数时丢失对象的赋值...

我试图猜测:它是否存在一种机制(使用变量或其他),密切关注对象函数的非重新配置,以便在发生这种情况时,这种机制会阻止this关键字的分配.平常(因为等于对象)?

T.J*_*der 7

原因相当微妙:thisJavaScript完全取决于函数的调用方式.要在调用期间this设置为,您必须在从对象中检索它时立即调用,如下所示:cargetNamegetNamecar

car.getName() // or
car["getName"]()
Run Code Online (Sandbox Code Playgroud)

(或通过Function#callFunction#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关键字).


Zir*_*rak 5

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,您logtoy对象的上下文中调用.但是,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)

......而且从这里来看很明显.