我可以在javascript中提供me / that / self = this的原型定义吗?

时间:2014-10-12 21:51:54

标签: javascript inheritance prototype

我更喜欢me / that / self方法来解决Javascript中的绑定“问题”。我随时声明一个'类',它将具有可作为参数传递的函数(例如事件处理程序)。以下是我的一般设置示例:

function Person(name)
{
    var me = this;

    this.name = name;

    this.alertName = function()
    {
        alert(me.name);
    };
}

var aPerson = new Person('Paul');
setTimeout(aPerson.alertName, 1000);

这是有效的,因为我在'class'定义中定义了var me = this;。这是重复的,所以作为练习,我想抽象一下并将me = this定义添加到Function的原型中,所以我不必每次都手动完成。我希望我描述它的方式是有道理的。我觉得这样的事情会奏效:

Function.prototype.me = function()
{
    return this;
}

我期望在Person'类'中的任何地方调用我(),但事实并非如此。我尝试了不同的方法,例如将Function扩展为具有定义的BaseFunction类,但我无法弄清楚,我无法通过Google或其他方式找到任何内容SO。

如果你有兴趣,这里有一个jsFiddle我一直在玩的东西:

http://jsfiddle.net/qgjw47nt/

谢谢,

4 个答案:

答案 0 :(得分:2)

您尝试使用me的方式(如果我正确理解您的问题),它将被视为分配给内部变量的函数,而不是函数/“对象”的成员本身。

要访问me原型,您必须使用this.me - 这当然会让整个事情变得毫无意义。

var foo = function()
{
    this.doSomething = function() {
        alert('yay!'); 
    };

    // this doesn't work! "me" would refer to a non-existent variable
    me.doSomething();

    // this would work, but it's obviously useless.
    this.me.doSomething();
}

更糟糕的是,如果您在另一个函数内定义的函数内调用this.me,您将访问内部函数的this.me,并且永远不能使用此方法访问外部函数

答案 1 :(得分:2)

您尝试定义me的方式是说您需要更加了解this。 函数的原型 - 是由new创建的所有对象的原型链。它完全不知道你的具体对象。

根据调用的位置调用处理程序,而不是您定义它的位置。 因此,没有从处理程序本身到它所属的对象的链接。

如何定义特定this并将其绑定到函数以便能够将其全部传递的方式,除了将this存储在闭包中之外,就像现在一样,是{{ 1}}功能。你可以这样做:

.bind()

实际上这是最真实的'如何在JS中完成它。当然有很多糖库可以用不同的形式包裹它们,但是所有的都有var foo = function (name) { this.name = name; this.handler = function () { console.log('I am called, name=', this.name); }.bind(this); } var boo = new foo('Paul'); setTimeout(boo.handler, 1000)

但是,如果你担心有重复的bind,那么任何其他选项对你来说也会是重复 :)检查CoffeeScript - 它是梦想的简约编码和梦魇来自其他方面。

答案 2 :(得分:1)

您可能知道在构造函数中定义的事件处理函数(或示例中的常规方法)将始终可以访问构造函数通过闭包调用的参数吗?试试这个。

function Person(name){
    this.alertName = function(){ 
        alert(name);
    };
}

这种模式的缺点是你不能将alertName放在Person的原型上,因为它需要通过闭包来访问私有参数。如果您不使用闭包,则绝对不需要在Person的每个实例上创建新的警报名称函数。

编辑:更正。 getter和setter同样糟糕,因为它们将闭包保留在内存中就像一个方法,没有想到它。因此,除非你真正好好利用它,否则你应该完全避免使用它,并在有疑问时使用原型。

<击> 您需要getter和setter来发布按值传递的变量。通过引用传递的变量可以通过this.yourPropertyName = yourArgumentName发布,因为它们只会引用同一个对象。

Object.defineProperty(this,"name",{
    get:function(){return name},
    set:function(newName){name = newName}
}); 

<击> 你不应该本身绑定它,而不是使用“this”。特别是在可能的情况下,您应该将它们放在原型上,并使它们成为通用的。术语“鸭型”通常用于此。因为如果你在你的方法中使用“this”,任何具有“name”属性的东西都可以使用Person.prototype.callName,它就会起作用(即使它是一个鸭子)。

答案 3 :(得分:0)

如果你发现JavaScript过于冗长,那就是CoffeeScript:

class Person
    constructor: (@name) ->
    alertName: => alert "Hi, my name is #{@name}"

aPerson = new Person 'chka chka Slim Shady'
setTimeout aPerson.alertName, 1000

这使用胖箭头=>),确保@(== this}绑定到正确的上下文。