Javascript 为什么实例不';在没有prototype关键字的情况下将t inherit属性添加到构造函数中

Javascript 为什么实例不';在没有prototype关键字的情况下将t inherit属性添加到构造函数中,javascript,Javascript,在本例中,一个名为“t”的属性被添加到speak函数中。speak.t=5当我调用speak()时,它会通过另一个名为show的函数打印值5。但是当我创建speak的新实例时,它不会继承属性t。为什么会这样?我的意思是,如果它是speak构造函数的属性,它的所有实例都应该继承它 <html> <body> <script> function Speak(){ show(Speak.t); } Speak.t=5; function show(v){

在本例中,一个名为“t”的属性被添加到speak函数中。
speak.t=5当我调用speak()时,它会通过另一个名为show的函数打印值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>
new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true

函数Speak(){
show(Speak.t);
}
t=5;
功能表演(五){
console.log('值为:'+v);
}
说();
var s1=新的Speak();
控制台日志(s1.t);
“我的意思是,如果它是Speak构造函数的属性,那么它的所有实例都应该继承它?”

new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true
不。它的实例继承自构造函数的原型,而不是构造函数本身。JavaScript基于原型,而不是“基于构造函数”。如果您熟悉,
Speak.t
将类似于公用电话

new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true
将其更改为
Speak.prototype.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
new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true

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

function SpecialSpeak(){}
SpecialSpeak.prototype = new Speak();
new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true
这将创建一个
Speak
实例,并将其指定为
SpecialSpeak
的原型

new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true
由于所有的
Speak
实例都将在其原型发生更改时更新,因此它还将更新
SpecialSpeak
的原型,并更新所有
SpecialSpeak
的实例

new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true
var s = new SpecialSpeak();
s.v;                             //undefined
Speak.prototype.v = "text";
s.v;                             //text
function Speak(){}
var obj = new Speak();
console.log("length" in Speak); // true
console.log("length" in obj); // false
这演示了继承如何在JavaScript中工作。原型的链接有时称为链接

new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true
您可能还想查看有关继承的信息

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

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

new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true
Object.prototype instanceof Object;    //false
虽然
Object.prototype
是一个对象,但它是所有*继承自的顶级原型(对象),因此它不是
Object
的实例。这就是目标

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

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

当对构造函数调用
new
操作符时,JavaScript引擎会在幕后执行一些步骤:

new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true
  • 它分配从构造函数原型继承的新对象
  • 它执行构造函数,将新创建的对象作为
    this
  • 如果构造函数返回一个对象,那么它将使用它。否则,它将使用
    对象
  • 它在任何时候都不会考虑附加到构造函数的类属性。这就是为什么
    Speak.t=5
    不创建继承属性的原因

    new SpecialSpeak() instanceof SpecialSpeak;     //true
    new SpecialSpeak() instanceof Speak;            //true
    
    但是,这些代码将执行以下操作:

    new SpecialSpeak() instanceof SpecialSpeak;     //true
    new SpecialSpeak() instanceof Speak;            //true
    
    // 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
      };
    }
    

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

    您可以阅读了解更多信息。

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

    new SpecialSpeak() instanceof SpecialSpeak;     //true
    new SpecialSpeak() instanceof Speak;            //true
    
    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
    方法来访问它的原型

    new SpecialSpeak() instanceof SpecialSpeak;     //true
    new SpecialSpeak() instanceof Speak;            //true
    
    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);
    

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

    new SpecialSpeak() instanceof SpecialSpeak;     //true
    new SpecialSpeak() instanceof Speak;            //true
    
    var s = new SpecialSpeak();
    s.v;                             //undefined
    Speak.prototype.v = "text";
    s.v;                             //text
    
    function Speak(){}
    var obj = new Speak();
    console.log("length" in Speak); // true
    console.log("length" in obj); // false
    
    对于例如函数,默认情况下获取一个名为length的属性(给出函数的arity) 不会与实例共享

    new SpecialSpeak() instanceof SpecialSpeak;     //true
    new SpecialSpeak() instanceof Speak;            //true
    
    var s = new SpecialSpeak();
    s.v;                             //undefined
    Speak.prototype.v = "text";
    s.v;                             //text
    
    function Speak(){}
    var obj = new Speak();
    console.log("length" in Speak); // true
    console.log("length" in obj); // false
    
    您可以非常清楚地看到,实例不共享长度。 在javascript中,共享属性或方法的唯一方法是通过原型模式

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

    以这种方式创建属性,使其行为类似于Speak上的
    静态
    变量

    我敢肯定,这必须是重复的,但是我找不到它。Speak。有些东西可能是静态的:原型由实例共享:我不理解您的第二个示例。您在另一个Speak函数中声明了另一个Speak函数。这很混乱。稍作解释会更好。无论如何,谢谢:)var Speak
    将包含自动执行功能。在这个自动执行的函数中,我创建了函数Speak并将
    t
    属性和
    show
    函数附加到他的原型中。现在清楚了吗?函数参数有长度属性。但是函数本身如何有长度属性。我的意思是Speak.length可能返回什么??例如,如果你说函数test(a,b){}。测试长度为2。length为您提供函数可以接受的参数数量。这只是断言了一个事实,即函数只是javascript@BOSS-
    .length
    不提供函数可以接受的参数数量。相反,它返回函数期望的参数数。父实例是否设置子对象的原型部分,子对象是否不重新使用父构造函数?参考一篇展示如何使用prototype的文章不是更好吗?@HMR-我已经添加了一个指向MDN继承文章的链接。
    new SpecialSpeak() instanceof SpecialSpeak;     //true
    new SpecialSpeak() instanceof Speak;            //true