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

js에서 객체를 생성하는 8가지 모드에 대한 간략한 설명

伊谢尔伦
풀어 주다: 2016-12-01 10:33:44
원래의
847명이 탐색했습니다.

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 的对象
로그인 후 복사

크롬에서 새로 생성된 각 객체의 차이점을 확인하세요.

js에서 객체를 생성하는 8가지 모드에 대한 간략한 설명

처음 6개 모드를 볼 수 있습니다 일곱 번째 차이점은 Object 객체이지만 속성이 없다는 것입니다(생성 시 프로토타입이 지정되지 않기 때문에 상속할 수 있는 속성이 없음도 포함)

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 类或子类
//工厂方法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. 생성자 패턴

//构造器方法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;
    }
}
로그인 후 복사

방법 1을 사용할 때의 문제점은 명백합니다. 새로운 객체가 생성되면 힙에 새로운 객체가 있어야 합니다. 개선 사항은 다음과 같습니다.

//构造器方法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());//通过构造器创建一个对象并调用其对象方法
로그인 후 복사

위의 문제는 의미가 충분히 명확하지 않다는 것입니다. 클래스의 캡슐화를 반영합니다.

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

함수가 선언될 때마다 실제로 Function 인스턴스 JS 함수가 생성된다는 것을 알고 있습니다.

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. 프로토타입 모드

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

方法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 受影响
로그인 후 복사

클래스의 프로토타입 필드에 있는 속성과 메서드가 포함되어 있는 것을 볼 수 있습니다. use 이 방법은 메모리 낭비를 줄여준다고 하지만 여전히 문제가 있습니다. 일단 객체의 속성이 변경되면 클래스에 의해 인스턴스화된 모든 객체의 proto에 있는 속성 값도 그에 따라 변경됩니다( 실제로는 레퍼런스임) 개선 사항은 다음과 같습니다

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

//每个对象有专属的属性不会与其他对象共享
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. 동적 프로토타입 모드

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);
로그인 후 복사

이 모드는 Java

와 같은 강력한 유형의 언어로 클래스 정의를 가능하게 합니다

function Car6(){
    var oTempCar = new Object;
    oTempCar.color = "blue";
    oTempCar.doors = 4;
    oTempCar.showColor = function () {
        alert(this.color);
    };
    return oTempCar;
}
var car6 = new Car6();
로그인 후 복사
. >


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

생성자 내부에 생성된 객체가 다시 전달됩니다. 변수 car6. 이 방법은 객체 메소드의 내부 관리에 사용됩니다. 기존 메소드(팩토리 메소드)와 동일한 문제점이 있으므로 최대한 피해야 합니다


저자: Tomson

원래 주소: http://segmentfault.com/a/1190000003862596


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿