一个方法可以在没有bind()的回调中引用它的对象吗?

时间:2012-02-15 10:38:58

标签: javascript oop bind

我正在制作一个测试用例来说明如何在回调中引用其函数的方法需要'bind'。

但就在我认为我认识JS时 - 下面的代码工作正常 - 不需要绑定!

pretendThingConstructor = function (greeting) {
    this.greeting = greeting;
    this.sayHello = function() {
        console.log(this.greeting);
    };
}

var pretend_thing = new pretendThingConstructor('hello world');

pretend_thing.sayHello();

setTimeout(function() {  
    pretend_thing.sayHello()
}, 3000);

当我运行它时 - 通过node,phantomjs或其他JS环境 - 它可以工作。 'hello world'打印两次。

我期待第二个“你好世界” - 一个在追赶结束后运行 - 失败,因为'this'将指的是事件,而不是对象。但它的确有效。这是为什么?

3 个答案:

答案 0 :(得分:2)

this的更改取决于调用函数的方式。如果指定基础对象,则会引用它:

pretend_thing.sayHello()

此处pretend_thing是该基础对象,因此this仍然引用该对象。另一方面,如果你有:

var f = pretend_thing.sayHello;
f();

此处this应该引用window对象。

您可以通过以下方式确认:

console.log (this instanceof pretendThingConstructor);

sayHello功能中。在这两种情况下都会打印true


pretendThingConstructor = function (greeting) {
    this.greeting = greeting;
    this.sayHello = function() {
        console.log(this.greeting);
        console.log(this instanceof pretendThingConstructor);
    };
}

var pretend_thing = new pretendThingConstructor('hello world');
////////////////////////////

pretend_thing.sayHello();

setTimeout(function() {  
    pretend_thing.sayHello();
}, 3000);

将输出:

true
true

,而:

var f = pretend_thing.sayHello;
f();

输出:

false

答案 1 :(得分:1)

在函数'pretendThingConstructor'的范围内,'this'指的是函数本身。当运行构造函数时(使用'new'关键字实例化对象时),sayHello方法(这是一个匿名方法)将被分配给实例化对象(在您的情况下为pretend_thing)的属性'sayHello'。

因为您正在调用'sayHello'方法来自'pretendThingConstructor'对象(pretend_thing)的实例,'this'指的是您正在调用方法的对象,而不是您正在执行的上下文英寸

您可以使用.apply方法更改'this'关键字的含义:

function myHello(){
    this.greeting = 'Hello';
    this.method = function(){
         this.greeting
    }
}

function myGoodbye(){
    this.greeting = 'Goodbye';
    this.say = function(){
         console.log( this.greeting );
    }
}

var hello = new myHello();
var goodbye = new myGoodbye();

hello.say(); // Outputs 'Hello'
goodbye.say(); // Outputs 'Goodbye'

hello.say.apply( goodbye ); // Outputs 'Goodbye'

答案 2 :(得分:0)

是的,在这种情况下,sayHello的this对象是pretend_thing,因为函数知道在哪个项目上调用它。如果您尝试这样做,这只会丢失:

< - language:lang-js - >

var say = pretend_thing.say_hello;
setTimeout(function () {
    say(); // this is window or null
}, 15)

// You can do something like
function doThings() {
    console.log(this.thing);
}

var test1 = { doThings: doThings, thing: 1 };
var test2 = { doThings: doThings, thing: 2 };

test1.doThings(); // <- 1
test2.doThings(); // <- 2

因此,上下文取决于函数的附加位置。但您可以使用bind-thing覆盖此行为。