我正在尝试了解foo.bar()var fn = foo.bar; fn();之间的区别

我整理了一个小例子,但我不完全理解为什么失败的人实际上会失败。

var Dog = function() {
    this.bark = "Arf";
};

Dog.prototype.woof = function() {
    $('ul').append('<li>'+ this.bark +'</li>');
};

var dog = new Dog();


// works, obviously
dog.woof();

// works
(dog.woof)();

// FAILS
var fnWoof = dog.woof;
fnWoof();


// works
setTimeout(function() {
    dog.woof();
}, 0);

// FAILS
setTimeout(dog.woof, 0);

产生:
  • Arf
  • Arf
  • 未定义
  • Arf
  • 未定义

  • 在JSFiddle上:http://jsfiddle.net/D6Vdg/1/

    因此,似乎关闭一个函数会导致其删除其上下文。好的。但是,为什么(dog.woof)();起作用呢?

    弄清楚这里发生了什么,这一切都令人困惑。显然有一些我不了解的核心语义。

    最佳答案

    问题出在上下文和this关键字上。

    函数并不是天生就“属于”对象。例如,我可以创建一个cat对象,并将woof函数复制到以下位置:

    var cat = {
        bark: "meow",
        woof = Dog.prototype.woof
    };
    

    现在cat.woof将给我“喵”声。由于要复制和重新分配的功能具有这种灵活性,因此var fnWoof = dog.woof;fnWoofdog解除关联-它没有上下文。因此,上下文以及this关键字默认为window。由于window没有bark属性,因此得到undefined

    如果给窗口树皮属性:
    window.bark = "Arf";
    

    然后您的代码将起作用(尽管有误):
    fnWoof(); // "Arf"
    

    为了使其按预期工作,您可以显式传递上下文:
    fnWoof.call(dog);
    

    09-26 22:29