4

关于这段代码:

var name = "Jaguar";
var car = {
  name:"Ferrari",
  getName:function(){
    return this.name;
  }
};

alert((car.getName = car.getName)());

输出是:Jaguar

为什么this对象对应Window而不是car变量中包含的对象?

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

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

4

4 回答 4

7

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

car.getName() // or
car["getName"]()

(或者通过Function#callor 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();

...这是不同的。以这种方式调用的函数被this设置为全局对象(window浏览器中的 , )。(在严格模式下除外;在严格模式下this将是undefined。)

更多(来自我贫血的博客):

它是否存在一种机制(使用变量或其他)来关注对象函数的非重新分配,以便如果发生这种情况,这种机制会像往常一样阻止 this 关键字的分配(等于等于物体)?

我不完全确定我是否遵循这个问题,但是如果您想要一个始终具有预设this值的函数,那么是的,有几种方法可以做到这一点。

一种是使用新的 ES5 功能bind

var name = "Jaguar";
var car = {
  name: "Ferrari"
};
car.getName = function(){
  return this.name;
}.bind(car);
alert((car.getName = car.getName)()); // "Ferrari"

bind返回一个始终this设置为您给它的参数的函数。

另一种方法是使用闭包。事实上,你可以bind很容易地在 ES3 中创建一个 -like 函数:

function pseudoBind(func, thisArg) {
    return function() {
        return func.apply(thisArg, arguments);
    };
}

这并不能做所有事情bind,但它确实起到了this作用。然后你会有:

var name = "Jaguar";
var car = {
  name: "Ferrari"
};
car.getName = pseudoBind(function(){
  return this.name;
}, car);
alert((car.getName = car.getName)()); // "Ferrari"

更多关于闭包的信息(同样来自博客):

在未来的规范中,我们将获得一种创建具有预设this值的函数的声明方式(所谓的“箭头函数”,因为它们的语法涉及使用=>而不是function关键字)。

于 2012-10-30T16:38:38.720 回答
5

啊,this决议......让我们看看。

var toy = {
    log : function () { console.log(this); }
};
toy.log() //logs the toy object

到目前为止,分辨率似乎this是静态的:无论方法在哪里定义,这就是它的this价值。

但!如果我们这样做会怎样:

var sneakyBastard = toy.log;
sneakyBastard(); //logs Window

this绑定到调用它的对象。在 的情况下toy.log,您log在对象的上下文中toy调用。但是,sneakyBastard没有设置上下文,所以就好像你调用了window.sneakyBastard.

现在让我们来看看你的表情(鹅?甘德?不......):

(car.getName = car.getName)()

...以及分配返回什么?分配的值,在这种情况下,是一个函数,car.getName。我们可以把这个表达式分成两部分:

var returnedValue = (car.getName = car.getName);
returnedValue();

...从这里很明显。

于 2012-10-30T16:43:41.267 回答
2

不是getName从对象的上下文调用,而是从分组运算符的返回结果的上下文调用它(在这种情况下没有上下文)

在 JavaScript 中,当没有定义明确的上下文时,使用默认值。默认是...

  • 严格模式下的全局对象

  • undefined处于严格模式

于 2012-10-30T16:37:35.743 回答
1

你已经把你的函数调用括号(())所以他们调用表达式的结果 (car.getName = car.getName)(这是分配给的值(一个函数)car.getName

于 2012-10-30T16:35:45.800 回答