Heim  >  Artikel  >  Web-Frontend  >  JS Core Series: Verstehen Sie den Funktionsmechanismus von New

JS Core Series: Verstehen Sie den Funktionsmechanismus von New

大家讲道理
大家讲道理Original
2017-01-24 11:28:051231Durchsuche

Wie andere Hochsprachen verfügt auch JavaScript über den neuen Operator. Wir wissen, dass der neue Operator zum Instanziieren einer Klasse und zum Zuweisen eines Instanzobjekts im Speicher verwendet wird. Aber in JavaScript ist alles ein Objekt. Warum müssen wir new verwenden, um Objekte zu generieren? Dieser Artikel führt Sie in die Geheimnisse des Neuen in JavaScript ein...

1. Lernen Sie den neuen Operator kennen:

function Animal(name){
        this.name = name;
    }
    Animal.color = "black";
    Animal.prototype.say = function(){
        console.log("I'm " + this.name);
    };
    var cat = new Animal("cat");

    console.log(
       cat.name,  //cat
       cat.height //undefined
    );
    cat.say(); //I'm cat

    console.log(
       Animal.name, //Animal
       Animal.color //back
    );
    Animal.say(); //Animal.say is not a function

1 . Codeinterpretation

Zeilen 1-3 erstellen eine Funktion Animal und definieren das Attribut: name darauf. Der Wert von name ist der formale Parameter, wenn die Funktion ausgeführt wird.

Zeile 4 definiert eine statische Eigenschaft: Farbe für das Animal-Objekt (Animal selbst ist ein Funktionsobjekt) und weist den Wert „schwarz“ zu.

Zeilen 5-7 definieren das Prototypobjekt des Tierfunktion Auf dem Prototyp wird eine say()-Methode definiert, und die say-Methode gibt den Namenswert davon aus.

Zeile 8 erstellt ein neues Objekt cat durch das neue Schlüsselwort

Zeilen 10-14 Das Katzenobjekt versucht, auf die Namens- und Farbattribute zuzugreifen und ruft die Methode say auf.

Die Zeilen 16–20 des Animal-Objekts versuchen, auf die Namens- und Farbeigenschaften zuzugreifen und die Say-Methode aufzurufen.

2. Schlüsselanalyse

Die 8. Codezeile ist der Schlüssel:

var cat = new Animal("cat");

JS-Engine führt dies aus Code Zu diesem Zeitpunkt wurde intern viel Arbeit geleistet und der Pseudocode wurde verwendet, um den Workflow wie folgt zu simulieren:

new Animal("cat") = {    var obj = {};

    obj.__proto__ = Animal.prototype;    var result = Animal.call(obj,"cat");    return typeof result === 'object'? result : obj;
}

(1)创建一个空对象obj;

(2)把obj的__proto__ 指向Animal的原型对象prototype,此时便建立了obj对象的原型链:obj->Animal.prototype->Object.prototype->null

(3)在obj对象的执行环境调用Animal函数并传递参数“cat”。 相当于var result = obj.Animal("cat")。

       当这句执行完之后,obj便产生了属性name并赋值为"cat"。

(4)考察第3步返回的返回值,如果无返回值或者返回一个非对象值,则将obj返回作为新对象;否则会将返回值作为新对象返回。

理解new的运行机制以后,我们知道cat其实就是过程(4)的返回值,因此我们对cat对象的认知就多了一些:

cat的原型链是:cat->Animal.prototype->Object.prototype->null

cat上新增了一个属性:name

分析完了cat的产生过程,我们再看看输出结果:

cat.name -> 在过程(3)中,obj对象就产生了name属性。因此cat.name就是这里的obj.name

cat.color -> cat会先查找自身的color,没有找到便会沿着原型链查找,在上述例子中,我们仅在Animal对象上定义了color,并没有在其原型链上定义,因此找不到。

cat.say -> cat会先查找自身的say方法,没有找到便会沿着原型链查找,在上述例子中,我们在Animal的prototype上定义了say,因此在原型链上找到了say方法。

另外,在say方法中还访问this.name,这里的this指的是其调用者obj,因此输出的是obj.name的值。

对于Animal来说,它本身也是一个对象,因此,它在访问属性和方法时也遵守上述查找规则,所以:

Animal.color -> "black"

Animal.name -> "Animal" , Animal先查找自身的name,找到了name,注意:但这个name不是我们定义的name,而是函数对象内置的属性。

一般情况下,函数对象在产生时会内置name属性并将函数名作为赋值(仅函数对象)。

Animal.say -> Animal在自身没有找到say方法,也会沿着其原型链查找,话说Animal的原型链是什么呢?

 从测试结果看:Animal的原型链是这样的:

 Animal->Function.prototype->Object.prototype->null

 因此Animal的原型链上没有定义say方法!

二、new存在的意义

认识了new运算符之后,我们再回到开篇提到的问题:JS中万物皆对象,为什么还要通过new来产生对象?要弄明白这个问题,我们首先要搞清楚cat和Animal的关系。

通过上面的分析,我们发现cat继承了Animal中的部分属性,因此我们可以简单的理解:Animal和cat是继承关系。

另一方面,cat是通过new产生的对象,那么cat到底是不是Animal的实例对象? 我们先来了解一下JS是如何来定义“实例对象”的?

A instanceof B

如果上述表达式为true,JS认为A是B的实例对象,我们用这个方法来判断一下cat和Animal

cat instanceof Animal; //true

从执行结果看:cat确实是Animal实例,要想证实这个结果,我们再来了解一下JS中instanceof的判断规则:

1 var L = A.__proto__;2 var R = B.prototype;3 if(L === R)4   return true;

如果A的__proto__ 等价于 B的prototype,就返回true

在new的执行过程(2)中,cat的__proto__指向了Animal的prototype,所以cat和Animal符合instanceof的判断结果。因此,我们认为:cat是Animal的实例对象。

简单的总结语

在javascript中, 通过new可以产生原对象的一个实例对象,而这个实例对象继承了原对象的属性和方法。因此,new存在的意义在于它实现了javascript中的继承,而不仅仅是实例化了一个对象!

 

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn