Heim > Web-Frontend > js-Tutorial > Eine kurze Diskussion über 8 Modi zum Erstellen von Objekten in js

Eine kurze Diskussion über 8 Modi zum Erstellen von Objekten in js

伊谢尔伦
Freigeben: 2016-12-01 10:33:44
Original
827 Leute haben es durchsucht

1.Objektmodus

var o1 = {};//字面量的表现形式
var o2 = new Object;
var o3 = new Object();
var o4 = new Object(null);
var o5 = new Object(undefined);
var o6 = Object.create(Object.prototype);//等价于 var o = {};//即以 Object.prototype 对象为一个原型模板,新建一个以这个原型模板为原型的对象
//区别
var o7 = Object.create(null);//创建一个原型为 null 的对象
Nach dem Login kopieren

Sehen Sie sich die Unterschiede zwischen jedem neu erstellten Objekt in Chrome an:

Eine kurze Diskussion über 8 Modi zum Erstellen von Objekten in js

Sie können die ersten 6 Modi sehen Die Objekte sind alle gleich. Der siebte Unterschied besteht darin, dass es zwar auch ein Objektobjekt ist, aber keine Attribute hat (einschließlich keiner Attribute, die vererbt werden können, da sein Prototyp bei der Erstellung nicht angegeben wird)

2. Factory-Muster

//工厂方法1 通过一个方法来创建对象 利用 arguments 对象获取参数设置属性(参数不直观,容易出现问题)
function createCar(){
    var oTemp = new Object();
    oTemp.name = arguments[0];//直接给对象添加属性,每个对象都有直接的属性
    oTemp.age = arguments[1];
    oTemp.showName = function () {
        alert(this.name);
    };//每个对象都有一个 showName 方法版本
    return oTemp;
}
createCar("tom").showName();//在 JS 中没有传递的实参,实际形参值为 undefined(这里的 age 为 undefined)
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类
//工厂方法2 通过传参设置属性(参数直观明了)
function createCar(name,age){
    var oTemp = new Object();
    oTemp.name = name;//直接给对象添加属性,每个对象都有直接的属性
    oTemp.age = age;
    oTemp.showName = function () {
        alert(this.name);
    };//每个对象都有一个 showName 方法版本
    return oTemp;
}
createCar("tom").showName();
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类
Nach dem Login kopieren

3. Konstruktormuster

//构造器方法1
function Car(sColor,iDoors){  //声明为构造器时需要将函数名首字母大写
    this.color = sColor;      //构造器内直接声明属性
    this.doors = iDoors;
    this.showColor = function(){
        return this.color;
    };//每个 Car 对象都有自己的 showColor方法版本
    this.showDoor = function () {
        return this.doors;
    }
}
Nach dem Login kopieren

Das Problem bei der Verwendung von Methode 1 ist offensichtlich Sobald ein neues Objekt erstellt wird, muss es neu im Heap sein. Die Verbesserungen sind wie folgt:

//构造器方法2
function showDoor(){      //定义一个全局的 Function 对象
    return this.doors;
}
function Car(sColor,iDoors){//构造器
    this.color = sColor;      //构造器内直接声明属性
    this.doors = iDoors;
    this.showColor = function(){
        return this.color;
    };
    this.showDoor = showDoor();//每个 Car 对象共享同一个 showDoor 方法版本(方法有自己的作用域,不用担心变量被共享)
}
alert(new Car("red",2).showColor());//通过构造器创建一个对象并调用其对象方法
Nach dem Login kopieren

Das Problem oben ist, dass die Semantik nicht klar genug ist Reflektieren Sie die Kapselung von Klassen.

4. Erstellen Sie durch Funktionsobjekte Objekt

Wir wissen, dass jedes Mal, wenn eine Funktion deklariert wird, tatsächlich eine Funktionsinstanz erstellt wird.

function function_name(param1,param2){alert(param1);}
//等价于
var function_name = new Function("param1","pram2","alert(param1);");
var Car2 = new Function("sColor","iDoors",
         "this.color = sColor;"+
         "this.doors = iDoors;"+
         "this.showColor = function(){ return this.color; }"
);
alert(new Car2("blue",3).showColor());
Nach dem Login kopieren

5. Prototypmodus Die von der Klasse

über das Prototypattribut hinzugefügten Attribute sind dieselben wie die Methoden, die an das Prototypfeld dieser Klasse (eigentlich ein Prototypobjekt) gebunden sind. Die an dieses Feld gebundenen Eigenschaften und Methoden haben nur eine Version und werden nur einmal erstellt.
Instanzobjekte der Klasse können direkt aufgerufen werden, so wie Ihre eigenen Attribute auch die Attribute und Methoden in der Prototypdomäne der Klasse aufrufen können. Die Klasse kann die Attribute und Methoden in der Prototypdomäne indirekt aufrufen, indem sie das Prototypattribut aufruft. Hinweis: Es gibt kein Prototypattribut im Objekt, nachdem das Objekt über die Klasse instanziiert wurde des Prototypfelds der Klasse auf die gleiche Weise wie beim Zugriff auf Eigenschaften. Das Instanzobjekt verfügt über ein privates Attribut proto, und das proto-Attribut enthält die Attribute und Methoden im Prototypfeld der Klasse

方法1
function Car3(){}//用空构造函数设置类名
Car3.prototype.color = "blue";//每个对象都共享相同属性
Car3.prototype.doors = 3;
Car3.prototype.drivers = new Array("Mike","John");
Car3.prototype.showColor = function(){
    alert(this.color);
};//每个对象共享一个方法版本,省内存。
var car3_1 = new Car3();
var car3_2 = new Car3();
alert(car3_1.color);//blue
alert(car3_2.color);//blue
alert(Car3.prototype.color);//blue
car3_1.drivers.push("Bill");
alert(car3_1.drivers);//"Mike","John","Bill"
alert(car3_2.drivers);//"Mike","John","Bill"
alert(Car3.prototype.drivers);//"Mike","John","Bill"
//直接修改实例对象的属性,解析器会先去找实例对象是否有这个属性(不会去找实例对象的 _proto_ 属性内的那些类的 prototype 属性,而是直接查看这个实例是否有对应的属性(与_proto_同级))
//如果没有则直接给这个实例对象添加该属性,但不会修改类的prototype域的同名属性,既实例对象的_proto_属性内的那些类 prototype 域属性不会被修改
car3_1.color = "red";//car3_1对象内无名为 color 的对象属性,故将该属性添加到该对象上
//解析器对实例对象读取属性值的时候会先查找该实例有无同名的直接属性
//如果没有,则查找__proto__属性内保存的那些 当前类的 prototype 域的属性
//有就返回,无则继续查找是否有原型链中的对应的方法属性
//有就返回,无则返回undefined
alert(car3_1.color);//red
alert(car3_2.color);//blue
alert(car3_2.color2);//undefined
//直接修改类的 prototype 域内的属性,不会影响该类的实例对象的对象属性,但会影响实例对象的_proto_属性(_proto_属性内存放的是类的 prototype 域的内容)
Car3.prototype.color = "black";
alert(car3_1.color);//red 该对象有同名的直接属性,故不会去_proto_属性内查找类的 prototype 域的属性
alert(car3_2.color);//black 受影响
//直接修改实例对象的方法,解析器会先去找实例对象是否有这个方法(不会去找实例对象的 _proto_ 属性内的那些类的 prototype 域的方法,而是直接查看这个实例是否有对应的方法(与_proto_同级))
//如果没有则直接给这个实例对象添加该方法,但不会修改类的prototype域的同名方法,既实例对象的_proto_属性内的那些类 prototype 域方法不会被修改
//car3_1对象内无名为 showColor 的对象方法属性,故将该方法属性添加到该对象上
car3_1.showColor = function () {
    alert("new function");
}
//解析器对实例对象调用方法属性的时候会先查找该实例有无同名的直接方法属性
//如果没有,则查找_proto_属性内保存的那些 当前类的 prototype 域的方法属性
//有就返回,无则继续查找是否有原型链中的对应的方法属性
//找到就返回,无则报错
car3_1.showColor();//new function
car3_2.showColor();//blue
car3_1.abcd();//直接报错
//直接修改类的 prototype 域内的方法属性,不会影响该类的实例对象的方法属性,但会影响实例对象的_proto_属性(_proto_属性内存放的是类的 prototype 域的内容)
Car3.prototype.showColor = function () {
    alert("second function");
}
car3_1.showColor();//new function 该对象有同名的方法属性,故不会去_proto_属性内查找类的 prototype 域的方法属性
car3_2.showColor();//second function 受影响
Nach dem Login kopieren
. Es ist ersichtlich, dass die Verwendung dieser Methode zwar die Speicherverschwendung reduziert, jedoch immer noch ein Problem darstellt. Sobald die Eigenschaften eines Objekts geändert werden, werden auch die Eigenschaftswerte im Proto aller von dieser Klasse instanziierten Objekte geändert entsprechend ändern (eigentlich handelt es sich um Referenzen)

Mischmodus aus Konstruktormodus und Prototypmodus

//每个对象有专属的属性不会与其他对象共享
function Car4(sColor,iDoors){
    this._color = sColor;//私有属性变量名称头加下划线标识
    this._doors = iDoors;
    this.drivers = new Array("Mike","John");//公有属性标识
}
//所有对象共享一个方法版本,减少内存浪费
Car4.prototype.showColor = function () {
    alert(this._color);
};
var car4_1 = new Car4("red",4);
var car4_2 = new Car4("blue",3);
car4_1.drivers.push("Bill");
alert(car4_1.drivers);//"Mike","John","Bill"
alert(car4_2.drivers);//"Mike","John"
Nach dem Login kopieren
Dies ist auch eine der häufig verwendeten Methoden zum Erstellen von Objekten

7. Dynamischer Prototypenmodus

function Car5(sColor,iDoors,iMpg){
    this.color = sColor;
    this.doors = iDoors;
    this.mpg = iMpg;
    this.drivers = new Array("Mike","John");
    //使用标志(_initialized)来判断是否已给原型赋予了任何方法,保证方法永远只被创建并赋值一次
    if(typeof Car5._initialized == "undefined"){//因为这里的标记是附加在类上,故如果后期直接对其进行修改,还是有可能出现再次创建的情况
        Car5.prototype.showColor = function () {//为Car5添加一个存放在 prototype 域的方法
            alert(this.color);
        };
        Car5._initialized = true;//设置一个静态属性
    }
}
var car5_1 = new Car5("red",3,25);
var car5_2 = new Car5("red",3,25);
Nach dem Login kopieren
Dieser Modus ermöglicht die Definition von Klassen in Sprachen wie Java

8 Fabrikmodus

function Car6(){
    var oTempCar = new Object;
    oTempCar.color = "blue";
    oTempCar.doors = 4;
    oTempCar.showColor = function () {
        alert(this.color);
    };
    return oTempCar;
}
var car6 = new Car6();
Nach dem Login kopieren
Aufgrund des Car6()-Konstruktors wird der neue Operator intern aufgerufen, sodass der zweite neue Operator (außerhalb des Konstruktors) ignoriert wird.

Das im Konstruktor erstellte Objekt Zurück zur Variablen car6. Diese Methode wird bei der internen Verwaltung der Objektmethode verwendet. Sie weist das gleiche Problem auf wie die klassische Methode (Factory-Methode). Sie sollte so weit wie möglich vermieden werden. Tomson
Ursprüngliche Adresse: http://segmentfault.com/a/1190000003862596


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage