0

在javascript中说我有:

var Person = (function () {

    function Person(data) {
        data = $.extend({
            name: "",
            age: 0
        }, data);

        this.name = data.name;
        this.age = data.age;
    }

    return Person;
})();

Person.prototype.getName = function () {
    return this.name;
};

...如果我在 javascript 中正确理解了“this”关键字,它可以引用几乎任何东西,从窗口对象到自身,再到介于两者之间的任何东西(例如对象的调用者)。我的问题是我到底如何编写像 .getName() 这样的方法,以便我知道如果我永远无法确定“this”将指的是什么,我将始终引用存储在 person 对象的 name 属性中的值那个方法?假设 .getName() 被调用并且“this”引用了窗口对象——那么我如何获得我需要的值呢?

我之所以问,是因为我已经使用相当繁重的原型设计继承了一些代码,并且我遇到了各种各样的问题,试图从它们内部引用对象的属性和方法。好像我遗漏了一些东西,但我整天都在研究范围、闭包和其他模式,但我无法解决这个问题。

4

2 回答 2

0

的值this由语言根据函数/方法的调用方式设置。

如果您有一个带有方法的对象并且您这样做:

obj.method()

然后,this将被设置为指向method()函数里面的对象。

但是,如果你只是像这样单独获得该方法:

var p = obj.method;
p();

然后,因为在实际的函数调用中没有对象引用,this将设置为window或者undefined取决于您是否处于严格模式。

此外,调用者可以使用或什至或从前面的示例准确指定他们想要this设置的内容。您可以在 MDN 上查看这些方法,以了解有关它们如何工作的更多详细信息。obj.method.call()obj.method.apply()p.call()p.apply()

因此,在您之前的代码中,这应该有效:

function Person(data) {
    data = $.extend({
        name: "",
        age: 0
    }, data);

    this.name = data.name;
    this.age = data.age;
}

Person.prototype.getName = function () {
    return this.name;
};

var p = new Person({name:"John"});
var n = p.getName();   // will return "John"

工作演示:http: //jsfiddle.net/jfriend00/a7MkP/


如果您需要传递getName()给不会使用对象上下文调用它的第三方库,那么有如下几个选项:

匿名函数:

var myPerson = new Person("John");
callThirdParty(function() {
    // callback that calls getName with the right object context
    return myPerson.getName();
});

使用.bind()(在某些较旧的浏览器中不支持):

var myPerson = new Person("John");
var boundFn = myPerson.getName.bind(myPerson);
callThirdParty(boundFn);

从你自己的方法:

var self = this;
callThirdParty(function() {
    // callback that calls getName with the right object context
    return self.getName();
});

Person仅供参考,您的构造函数周围的自执行函数确实没有理由。它只是使代码更复杂,在这种情况下没有任何价值。

于 2013-02-14T23:22:51.047 回答
-1

是的,您正确理解了this关键字

我到底是如何编写 .getName() 之类的方法,以便我知道我将始终引用存储在 person 对象的 name 属性中的值

您只能通过不使用this, 和不使用原型来做到这一点。给每个对象一个始终引用原始对象的唯一函数:

function Person(data) {
    data = $.extend({
        name: "",
        age: 0
    }, data);

    this.name = data.name;
    this.age = data.age;

    var that = this; // a reference variable always pointing to this instance
    this.getName = function() {
        // using the variable from the constructor closure
        return that.name; // a quite useless getter
    };
}

var john = new Person({name:"John"}),
    getter = john.getName;
getter(); // "John"

我遇到了各种各样的问题,试图从自身内部引用对象的属性和方法

因此,通过上述方法,您可以通过使所有方法都特定于实例来解决它。但是,这会破坏原型设计的所有优势,因此不应使用.

相反,调用函数(或方法)的人应该负责在正确的上下文中调用它:

john.getName();

如果你真的必须将一个函数传递给忽略它的人(比如addEventListener),你可以使用类似的魔法东西.bind()或者只是应用上面的模式:

// from
addEventListener("click", john.sayHello); // will call the function in context of the DOM
// to
addEventListener("click", function() {
    john.sayHello(); // correct thisValue
});
于 2013-02-14T23:18:30.227 回答