2013-06-28 61 views
4

之间有什么区别:差异挂钩之间的功能到原型或不

function Gandalf() { 
    this.color = 'grey'; 
} 

Gandalf.prototype.comeBack = function() { 
    this.color = 'white'; 
} 

和:

function Gandalf() { 
    this.color = 'grey'; 

    this.comeBack = function() { 
     this.color = 'white'; 
     return this; 
    }; 
} 

以及在何种情况下,我应该钩法上的原型,还是没有?

+4

取决于你有多少Galdalfs。 – georg

+0

[在Javascript中使用'prototype'与'this'?](http://stackoverflow.com/questions/310870/use-of-prototype-vs-this-in-javascript) –

+1

@ thg435取决于你有多少__Galdalfs__?你由于错字而毁了一个很棒的评论。 –

回答

4

好吧代理凯,我会以不同于Esailija的方式来处理这个问题。我们从简单的对象开始。例如说,你已经有一个对象调用gandalf

var gandalf = { 
    color: "grey", 
    comeBack: function() { 
     this.color = "white"; 
     return this; 
    } 
}; 

有这个代码没有构造函数。因此这段代码很容易理解。我是对的还是对的?


好的,现在我要去做一些真棒。我会从gandalf创建radagast

var radagast = Object.create(gandalf); 

radagast.color = "brown"; 

这里发生了什么?让我们来打破它:

  1. 我们使用Object.creategandalf创建一个名为radagast新对象。因此radagast继承自gandalf
  2. 我们将colorradagast设置为棕色而不是灰色。

为了使它更加简单想象一下你和我有以下的对话:

I: Hey Agent Kay, I met Radagast yesterday.

U: Who's Radagast?

I: Hmm... do you know who's Gandalf?

U: Yes, I do.

I: Well Radagast is just like Gandalf except that he's brown instead of white.

这正是继承在JavaScript中的工作原理。你看到JavaScript有原型继承。在原型继承中,对象从其他对象继承。在这种情况下,radagast继承自gandalf


现在他们的方式原型继承通常在JavaScript中实现是很奇怪的。我称之为constructor pattern of prototypal inheritance。当您创建的Gandalf一个实例并实例继承什么对象

function Gandalf() { 
    this.color = "grey"; 
} 

Gandalf.prototype.comeBack = function() { 
    this.color = "white"; 
    return this; 
}; 

现在:例如,把你的代码?它从Gandalf.prototype继承:

var gandalf = new Gandalf; 
alert(Object.getPrototypeOf(gandalf) === Gandalf.prototype); // true 

发生了什么事时,你说new Gandalf是:

var gandalf = Object.create(Gandalf.prototype); 
Gandalf.call(gandalf); 

如果展开Gandalf.call(gandalf)的你:

var gandalf = Object.create(Gandalf.prototype); 
gandalf.color = "grey"; 

现在把你的第二个例子:

function Gandalf() { 
    this.color = "grey"; 

    this.comeBack = function() { 
     this.color = "white"; 
     return this; 
    }; 
} 

在当你创建的Gandalf一个实例这种情况下,你基本上这样做:

var gandalf = Object.create(Gandalf.prototype); 

gandalf.color = "grey"; 

gandalf.comeBack = function() { 
    this.color = "white"; 
    return this; 
}; 

因此,你创建一个新的Gandalf每次创建一个新的功能comeBack。因此,如果您拨打new Gandalf 10次,您也将拥有10个不同的comeBack功能。

与此相比,在第一个例子,因为comeBack是在Gandalf.prototype定义,我们每次打电话new Gandalf时候我们得到一个新的对象,从Gandalf.prototype继承。因此,只有一个comeBack函数在Gandalf的所有实例中共享。这不是更好吗?


本质上认为你的第一个例子是这样的:

var gandalfPrototype = { 
    create: function() { 
     var gandalf = Object.create(this); 
     gandalf.color = "grey"; 
     return gandalf; 
    }, 
    comeBack: function() { 
     this.color = "white"; 
     return this; 
    } 
}; 

var gandalf = gandalfPrototype.create(); // there's only one comeBack function 

同样你的第二个例子是相同的:

var gandalfPrototype = { 
    create: function() { 
     var gandalf = Object.create(this); 

     gandalf.color = "grey"; 

     gandalf.comeBack = function() { 
      this.color = "white"; 
      return this; 
     }; 

     return gandalf; 
    } 
}; 

var gandalf = gandalfPrototype.create(); // there's 1 comeBack for each instance 

请记住,当你一个函数之前使用new给你打电话实际上是继承了该函数的prototype。不是功能本身。


最后,我想说的(因为我J.R.R.托尔金的忠实粉丝),这是我会写代码的方式:

var wizard = { 
    create: function (color) { 
     var wizard = Object.create(this); 
     wizard.color = color; 
     return wizard; 
    } 
}; 

var gandalf = wizard.create("grey"); 

gandalf.comeBack = function() { 
    this.color = "white"; 
    return this; 
}; 

var saruman = wizard.create("white"); 
var radagast = wizard.create("brown"); 

感谢您阅读我的答案。

+0

saras !!! Su回答dedo che aadit bhai ...我记得你用一种非常简单的方式回答了我的问题!!!看起来proto是你的特长..把它撑起来Chokraa !!! – 2013-06-29 23:03:07

+0

非常聪明和简洁的答案,很多你的先生的荣誉! – Kay

+0

'因此,每次创建新的甘道夫时,都会创建一个新函数comeBack。因此,如果您将新的Gandalf调用10次,那么您将拥有10种不同的comeBack函数。 在第一个例子中,由于comeBack是在Gandalf.prototype上定义的,所以每次我们调用新的Gandalf时,都会得到一个从Gandalf.prototype继承的新对象。因此,只有一个在所有Gandalf实例中共享的comeBack函数。是不是更好?“有点难以理解......我可以对它进行简短的夸张......评论会做 –

3

把它放在原型上的原因是因为每个创建的对象都可以使用相同的函数对象(函数只是可调用的对象),它们只需要不同的标识和数据。但在第二种情况下,即使可以使用相同的函数对象,也可以为每个对象创建唯一的函数对象。

既然你似乎知道PHP,所不同的是在PHP类似:

class Gandalf { 
    public $color = "grey"; 

    public function comeBack() { 
     $this->color = "white"; 
    } 
} 


class Gandalf { 
    public $color = "grey"; 

    //Create the method inside constructor everytime 
    public function __construct() { 
     $this->comeBack = function() { 
      $this->color = "white"; 
      return $this; 
     }->bindTo($this, $this); 
    } 
} 

这是很难说什么时候使用其他时候表现不是一个问题。个人而言,构造函数和additional indentation level的模糊处理足以让我更喜欢原型。

+0

请注意,即使函数对象本身是重复的,他们可以共享他们的代码(但不是作用域链) –

+0

@JanDvorak我并不是说代码是重复的,那将是疯狂的。让我澄清一下。 – Esailija

0

地回答:

在何种情况下,我应该勾法到原型,还是没有?

如果您有一个函数需要访问使用构造函数创建的对象的专用vars,它需要位于构造函数的内部。

function Gandalf() { 
    var age = '30000'; //approximate 

    this.alertAge1 = function() { 
     alert(age); 
    }; 
} 

Gandalf.prototype.alertAge2 = function() { 
    // age not visible from here 
};