为什么实例没有继承在没有prototype关键字的情况下添加到构造函数的属性

时间:2014-08-29 07:16:01

标签: javascript

在这个例子中,一个名为“' t'添加说话功能。Speak.t=5;当我调用speak()时,它通过另一个名为show.But的函数输出值5当我创建Speak的新实例时,它不会继承属性t。为什么所以我的意思是,如果它是Speak构造函数的一个属性,它的所有实例都应该继承它吗?

<html>
<body>
<script>
function Speak(){

    show(Speak.t);
}
Speak.t=5;
function show(v){
    console.log('value is : '+v);
}
Speak();
var s1=new Speak();
console.log(s1.t);
</script>
</body>
</html>

4 个答案:

答案 0 :(得分:4)

  

&#34;我的意思是如果它是Speak构造函数的属性,它的所有实例都应该继承它吗?&#34;

没有。它的实例继承自构造函数的原型,而不是构造函数本身。 JavaScript是基于原型的,而不是#34;基于构造函数的#34;。如果您熟悉other OOP languages,则Speak.t 类似与公众static property

将其更改为Speak.protoype.t = 5会将属性t: 5添加到原型中,该原型将继承到其所有实例:

function Speak(){
    show(this.t);
}
Speak.prototype.t = 5;

function show(v){
    console.log('value is : '+v);
}

var s1 = new Speak();    //"value is : 5"
console.log(s1.t);       //5

由于实例继承自其构造函数的原型,您实际上可以通过执行以下操作来实现类继承:

function SpecialSpeak(){}
SpecialSpeak.prototype = new Speak();

这会创建一个Speak实例并将其指定为SpecialSpeak的原型。

new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true

由于所有Speak个实例的原型发生变化后都会更新,因此它还会更新SpecialSpeak的原型并更新所有SpecialSpeak个实例

var s = new SpecialSpeak();
s.v;                             //undefined
Speak.prototype.v = "text";
s.v;                             //text

这演示了继承在JavaScript中的工作原理。原型的链接有时称为"prototype chain"

您可能还想查看有关继承的this great article


旁注:由于所有原型链都必须有一个起点,

Object.prototype instanceof Object;    //false

虽然Object.prototype是一个对象,但它是 * 所有内容的最顶层原型(对象),因此它不是Object的实例。它是 对象!

* 从ES5开始,引入了Object.create,允许您创建不会从Object.prototype继承的对象。

答案 1 :(得分:1)

当在构造函数上调用new运算符时,JavaScript引擎会在场景后面执行几步:

  1. 它分配一个从构造函数的原型继承的新对象
  2. 执行构造函数,将新创建的对象作为this
  3. 传递
  4. 如果构造函数返回一个对象,那么它会使用它。否则,它使用this对象。
  5. 在任何时候它都不会考虑附加到构造函数的类属性。这就是Speak.t = 5不创建继承属性的原因。

    然而,这些代码将会:

    // By attaching `t` to the prototype
    function Speak1() {}
    Speak1.prototype.t = 5;
    
    // By attaching `t` to the newly created object
    function Speak2() {
      this.t = 5;
    }
    
    // By returning an object containing `t` (thus overriding the formerly allocated this)
    function Speak3() {
      return {
        t: 5
      };
    }
    

    DEMO

    您可以阅读here了解详情。

答案 2 :(得分:1)

这是因为您没有在内部设置t的值。你应该在Speak的构造函数中实例化t的值,如下所示:

function Speak(){
  this.t = 5;
  show(this.t);
}
function show(v){
    console.log('value is : '+v);
}
Speak();
var s1=new Speak();
console.log(s1.t);

您还可以在构造函数中附加show方法来访问它的原型。

var Speak = (function() {
  function Speak() {
    this.t = 5;
    this.show();
  }

  Speak.prototype.show = function() {
    return console.log('value is : ' + this.t);
  };

  return Speak;

})();

var s1=new Speak();
console.log(s1.t);

答案 3 :(得分:1)

因为函数只是对象t成为Speak函数的属性,而不是与实例共享。

对于例如默认情况下的函数获取一个名为length的属性(给出函数的arity) 不会与实例共享。

function Speak(){}
var obj = new Speak();
console.log("length" in Speak); // true
console.log("length" in obj); // false

您可以清楚地看到长度未与实例共享。 在javascript中,共享属性或方法的唯一方法是通过原型模式。

以这种方式创建属性,使其在Speak

上的行为类似于static变量