Maison >interface Web >js tutoriel >Une brève discussion sur 8 modes de création d'objets en JS
1.Mode Objet
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 的对象
Affichez les différences entre chaque nouvel objet dans Chrome :
On peut voir que les objets créés par les 6 premiers modes sont tous identiques. La septième différence est que bien qu'il s'agisse également d'un objet Objet, il n'a aucun attribut (y compris aucun attribut pouvant être hérité, car il n'est pas précisé lors de la création de son prototype)
2. Patron d'usine
//工厂方法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 类或子类
3. Patron de constructeur
//构造器方法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; } }
Le problème avec l'utilisation de la méthode 1 est évident. Il n'y a aucun moyen de réutiliser la méthode showDoor. Chaque fois qu'un nouvel objet est créé, un nouvel espace sera ouvert dans le tas.
//构造器方法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());//通过构造器创建一个对象并调用其对象方法Le problème ci-dessus est que la sémantique n'est pas suffisamment claire pour refléter l'encapsulation des classes, améliorée en mode prototype
4 Créer des objets via des objets Fonction Nous savons que chaque fonction déclarée est en fait créée Une fonction JS d'instance de fonction.
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());5. Mode prototype
Les attributs et les méthodes ajoutées par l'attribut prototype de la classe sont liées à cette classe. Dans le champ prototype (en fait un objet Prototype), les propriétés et méthodes liées à ce champ n'ont qu'une seule version et ne seront créées qu'une seule fois.
L'objet instance de la classe peut appeler directement les propriétés de la classe, tout comme pour appeler ses propres propriétés. Pour les propriétés et méthodes du domaine prototype, la classe peut indirectement appeler les propriétés et méthodes du domaine prototype en appelant la propriété prototype Remarque : Une fois l'objet instancié via la classe, il n'y a pas de propriété prototype dans l'objet, mais l'objet peut accéder directement aux propriétés comme Pour accéder au contenu du champ prototype de la classe, l'objet instance a un attribut privé
proto
, et l'attribut proto contient les attributs et méthodes dans le champ prototype de la classe
方法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 受影响proto
de tous les objets instanciés par cette classe seront également modifiées en conséquence (en fait, c'est le cas. une référence), et les améliorations sont les suivantes
6 Mode mixte de méthode constructeur et de méthode prototypeC'est également une méthode de création couramment utilisée. objets. Un
//每个对象有专属的属性不会与其他对象共享 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"7. Mode prototype dynamique
Ce mode permet la définition de classes dans des langages tels que les langages fortement typés comme Java.
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);8. Modèle d'usine mixte
Puisque le nouvel opérateur est appelé à l'intérieur du constructeur Car6(), le deuxième nouvel opérateur (situé à l'extérieur du constructeur) sera être ignoré ),
function Car6(){ var oTempCar = new Object; oTempCar.color = "blue"; oTempCar.doors = 4; oTempCar.showColor = function () { alert(this.color); }; return oTempCar; } var car6 = new Car6();L'objet créé à l'intérieur du constructeur est renvoyé à la variable car6. Cette méthode présente les mêmes problèmes que la méthode classique (méthode usine) dans la gestion interne de la méthode objet. autant que possible.
Ceci est une brève discussion des 8 modes de création d'objets JS. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !