>웹 프론트엔드 >JS 튜토리얼 >JS에서 객체를 생성하는 8가지 모드에 대한 간략한 토론

JS에서 객체를 생성하는 8가지 모드에 대한 간략한 토론

黄舟
黄舟원래의
2017-02-24 13:39:471038검색


1.객체 모드

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 的对象

Chrome에서 각 새 객체의 차이점 보기:
JS에서 객체를 생성하는 8가지 모드에 대한 간략한 토론

처음 6개 모드에서 생성된 객체는 모두 동일함을 알 수 있습니다. 일곱 번째 차이점은 객체 객체임에도 불구하고 프로토타입이기 때문에 상속할 수 있는 속성이 없다는 점입니다. 생성 시 지정되지 않음) )

2. 팩토리 패턴

//工厂方法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 类或子类
rrree

3. 생성자 패턴

//工厂方法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 类或子类

방법 1을 사용할 때의 문제점은 명백합니다. showDoor 메소드를 재사용할 수 있는 방법은 없습니다. 새로운 객체가 생성될 때마다 힙에 새로운 공간이 열리게 됩니다. 개선 사항은 다음과 같습니다.

//构造器方法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;
    }
}

문제는 다음과 같습니다. 위의 내용은 의미가 명확하지 않고 클래스의 캡슐화를 반영할 수 없다는 것입니다. 프로토타입 모드의 개선 사항

4. 함수 객체를 통해 객체 생성

함수가 선언될 때마다 실제로 Function 인스턴스 JS 함수가 생성됩니다.

//构造器方法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());//通过构造器创建一个对象并调用其对象方法
function function_name(param1,param2){alert(param1);}
//等价于
var function_name = new Function("param1","pram2","alert(param1);");

5.prototype 모드

prototype 속성에 의해 추가되는 속성과 메소드는 다음과 같습니다. 이 클래스의 프로토타입 필드(실제로는 Prototype 객체)에 바인딩됩니다. 도메인에는 속성과 메서드의 버전이 하나만 있으며 한 번만 생성됩니다.
클래스의 인스턴스 객체는 직접 호출할 수 있습니다. 클래스의 프로토타입 필드의 속성과 메소드는 자체 속성을 호출하는 것과 마찬가지로 프로토타입 속성을 호출하여 간접적으로 호출할 수 있습니다.
참고: 객체가 인스턴스화되면 클래스를 통해 객체에는 프로토타입 속성이 없지만 속성에 액세스하는 것처럼 객체는 클래스의 프로토타입 도메인 내용에 직접 액세스할 수 있습니다. proto 속성에는

var Car2 = new Function("sColor","iDoors",
         "this.color = sColor;"+
         "this.doors = iDoors;"+
         "this.showColor = function(){ return this.color; }"
);
alert(new Car2("blue",3).showColor());
클래스의 프로토타입 도메인에 있는 속성과 메서드가 포함되어 있습니다. 이 메서드를 사용하면 메모리 낭비가 줄어들지만 여전히 문제가 있음을 알 수 있습니다. 객체가 변경되면 이 클래스에 의해 인스턴스화된 모든 객체의 proto

에 있는 속성 값도 변경됩니다(실제로 참조). 개선 사항은 다음과 같습니다

6 . 생성자 모드와 프로토타입 모드의 혼합

方法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 受影响
이것도 객체 생성에 흔히 사용되는 방법 중 하나입니다

7. >

//每个对象有专属的属性不会与其他对象共享
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"

이 모드는 java

8. Car6()에서는 new 연산자가 생성자 내부에서 호출되므로 두 번째 new 연산자(생성자 외부에 있음)는 무시됩니다.

생성자 내부에서 생성된 객체는 이 방식으로 car6 변수에 다시 전달됩니다. 객체 메소드 내부 관리는 고전적인 메소드(팩토리 메소드)와 동일한 문제가 있으므로 최대한 피해야 합니다.

위는 JS를 사용하여 객체를 생성하는 8가지 모드에 대한 간략한 설명입니다. 더 많은 관련 내용은 PHP 중국어 웹사이트(www.php.cn)를 주목해주세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.