我可以用javascript提供我/the/self=this的原型定义吗



我更喜欢me/the/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);

这之所以有效,是因为我在"类"定义中定义了var me = this;。这是重复的,所以作为一个练习,我想将其抽象出来,并将me = this定义添加到Function的原型中,这样我就不必每次都手动执行。我希望我描述它的方式有意义。我以为这样的东西会起作用:

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

我本以为在Person"class"中的任何位置调用me()都可以,但事实并非如此。我尝试过不同的方法,例如用一个有定义的BaseFunction类扩展Function,但我无法理解,也无法通过谷歌或SO找到任何东西。

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

http://jsfiddle.net/qgjw47nt/

谢谢,

Paul

您试图定义me的方式表明,您需要更深入地了解this。函数的原型-是您通过new创建的所有对象的原型链。这是完全不知道你的具体对象。

使用上下文调用处理程序取决于它被调用的位置,而不是您定义的位置。所以,并没有从处理程序本身到它所属对象的链接。

除了像现在这样将this存储在闭包中之外,您还可以定义特定的this并将其绑定到函数,以便能够将其四处传递,这就是.bind()函数。你可以做一些类似的事情:

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)

事实上,这是JS中最"真实"的方式。当然,有很多不同形式的糖库,但都有bind

但是,如果你担心有重复的var me = this,任何其他选项对你来说都太过了:)查看CoffeeScript-这是极简主义编码的梦想,也是其他方面的噩梦。

您尝试使用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,而使用这种方法永远无法访问外部函数。

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

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",那么任何具有"name"属性的东西都可以使用Person.prototype.callName,它就会正常工作(即使它是一只鸭子)。

如果你觉得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)绑定到正确的上下文。

最新更新