> 웹 프론트엔드 > JS 튜토리얼 > 프로토타입을 통한 JavaScript 객체 생성 및 객체 생성 이해

프로토타입을 통한 JavaScript 객체 생성 및 객체 생성 이해

巴扎黑
풀어 주다: 2017-08-09 11:21:39
원래의
916명이 탐색했습니다.


1. 객체를 생성하는 여러 가지 방법

1. 독립 선언 모드

var box1 = new Object();	//声明第一个对象并给各属性赋值
box1.name = 'Lee';
box1.age = 100;
box1.run = function () {
	return this.name + this.age + '运行中...';
};
alert(box.run());

var box2 = new Object();	//声明第二个对象并给属性赋值
box2.name = 'Jack';
box2.age = 200;
box2.run = function () {
	return this.name + this.age + '运行中...';
};
alert(box2.run());
로그인 후 복사

이때 box2와 box1은 서로 독립적이므로 혼동되지 않습니다.

그런데 동일한 구조의 객체를 선언할 때마다 코드를 추가해야 하는 것이 특히 불편하므로 다음과 같은 팩토리 패턴을 사용합니다.

2. 팩토리 모드

function createObject(name, age) { //集中实例化的函数
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	obj.run = function () {
		return this.name + this.age + '运行中...';
	};
	return obj;
}
로그인 후 복사

이렇게 하면 새 객체를 생성할 때마다 createObject() 메서드만 호출하면 됩니다. 동시에 매개변수를 전달하여 객체를 초기화할 수도 있습니다.
그러나 new로 생성된 객체는 모두 Object에 종속되므로 new로 생성된 객체 사이에 몇 가지 본질적인 구분을 적용하려는 경우 현재로서는 더 간단한 생성자 패턴이 작동하지 않습니다.

3. 생성자 패턴

function Box(name, age) {
	this.name = name;
	this.age = age;
	this.run = function () {
		return this.name + this.age + '运行中...';
	};
}
var box1 = new Box('Lee', 100);
var box2 = new Box('Jack', 200);
alert(box1.run());
alert(box1 instanceof Box); //很清晰的识别他从属于Box
로그인 후 복사

생성자 패턴은 객체 재사용 및 매개변수 초기화 문제를 크게 해결했으며 가장 일반적으로 사용되는 새로운 객체 패턴입니다.
참고:

herebox1.run != box2.run, 참조 주소를 결정하기 때문에 두 객체의 메소드가 서로 다른 위치에 저장되어 있으며 서로 다른 메소드임을 알 수 있습니다.
그러나 box1.run() == box2.run(), 동일한 값을 반환하기 때문입니다.
객체가 있으면 자연스럽게 객체 속성과 메서드를 공유하게 됩니다. 예를 들어 Java에서는 하위 클래스가 상위 클래스의 멤버 변수와 메서드를 공유합니다.
직접 말하면 생성자 패턴에 의해 생성된 객체는 서로 독립적입니다(예: 위의 box1.run != box2.run). 두 객체 간에 특정 속성을 공유하려면 프로토타입 프로토타입을 사용해야 합니다. .

2. 프로토타입을 통해 객체 생성

1. 프로토타입 모드

function Box() {} //声明一个构造函数
Box.prototype.name = 'Lee'; //在原型里添加属性
Box.prototype.age = 100;
Box.prototype.arr = ['aaa','bbb'];
Box.prototype.run = function () { //在原型里添加方法
	return this.name + this.age + '运行中...';
};
var box1 = new Box();
var box2 = new Box();

//修改普通属性,看下会不会影响prototype
alert(box1.name);	//Lee
box1.name = 'Rinima';
alert(box1.name);	//Rinima
alert(box2.name);	//Lee,修改box1的普通属性,相当于直接在box1中添加一个属性,是不会牵扯到原型中的属性的。
					//这一点非常好。但是如果是引用对象(数组)的话,就有问题了。

//修改引用属性,看下会不会影响prototype
alert(box1.arr);	//aaa,bbb
box1.arr.push('ccc');
alert(box1.arr);	//aaa,bbb,ccc
alert(box2.arr);	//aaa,bbb,ccc,修改box1的引用属性,却牵扯到了原型中的属性。
			//这是因为arr只是个引用地址,指向数组真实存储的位置,修改box1中的引用属性就是修改引用所指向的数组,所以原型也被修改了
			//这是我们不希望看到的!
로그인 후 복사

이 모드의 장점:

1. 이때 프로토타입에 있는 새 객체의 속성이 공유됩니다. box1.run = = box2.run
2. 새 객체 인스턴스의 속성이 완전히 통합되도록 할 수 있습니다(단점 2와 반대).
이 모드의 단점:

1. 참조 유형 객체에서 참조 속성을 직접 수정하면 모든 객체의 참조 속성이 수정됩니다
2. 이 모드에서는 초기화 매개변수 전송이 생략되므로 new에서 나오는 모든 속성이 동일합니다.

1.1. 프로토타입 리터럴 모드

(프로토타입 모드의 또 다른 모드, 일반적으로 큰 차이가 없으며 둘 다 프로토타입 모드에 속함)

function Box() {};
Box.prototype = { //使用字面量的方式
	constructor : Box,
	name : 'Lee',
	age : 100,
	run : function () {
		return this.name + this.age + '运行中...';
	}
};
로그인 후 복사

이 모드는 프로토타입 모드의 모든 장점과 단점을 상속받습니다. 고유한 장점과 단점도 있습니다.
장점: 캡슐화를 더 잘 반영합니다.
단점: 생성자는 자신을 가리키지 않으며 수동으로 지정해야 합니다.

2. 생성자 + 프로토타입 모드

function Desk(name, age) { //不共享的使用构造函数
	this.name = name;
	this.age = age;
	this.family = ['aaa', 'bbb', 'ccc'];
};
Desk.prototype = { //共享的使用原型模式
	constructor : Desk,
	run : function () {
		return this.name + this.age + this.family;
	}
};

var desk1 = new Desk('Lee',100);
var desk2 = new Desk('Jack',200);
alert(desk1.family);	//aaa,bbb,ccc
desk1.family.push('ddd');
alert(desk1.family);	//aaa,bbb,ccc,ddd
alert(desk2.family);	//aaa,bbb,ccc
로그인 후 복사

장점 : 이 모드는 공유속성과 비공유속성의 문제를 완벽하게 해결하고, 정밀하게 제어할 수 있는 아주 좋은 모드입니다.
단점: 그러나 이 방법에서는 프로토타입과 생성자가 분리되어 있어 사람들이 이상하게 느낄 수 있고 캡슐화가 반영되지 않습니다.

3. 동적 프로토타입 모드

function Box(name ,age) { //将所有信息封装到函数体内
	this.name = name;		//不共享的属性
	this.age = age;
	
	if (typeof this.arr != 'object') {		//共享的属性
		alert('在第一次调用的时候...arr');
		Box.prototype.arr = ['aaa','bbb'];
	}
	if (typeof this.run != 'function') {
		alert('在第一次调用的时候...run');
		Box.prototype.run = function () {
			return this.name + this.age + '运行中...';
		};
	}
}
var box1 = new Box();
var box2 = new Box();
alert( box1.arr );		//aaa,bbb
box1.arr.push('ccc');
alert( box1.arr );		//aaa,bbb,ccc
alert( box2.arr );		//aaa,bbb
로그인 후 복사


장점: 이 모드는 이전 모드(구성 + 프로토타입)의 모든 장점을 상속하고 캡슐화 문제도 완벽하게 해결합니다.
참고: 이 모드에서 프로토타입을 작성할 때는 리터럴을 사용할 수 없습니다. 인스턴스와 새 프로토타입 간의 연결이 끊어집니다. ? ? ?

기본적으로 현 시점에서는 위의 두 가지 모드가 대부분의 문제를 처리할 수 있으며 더 나은 모드입니다.
그러나 다음 두 가지 대체 모드를 사용해야 하는 비교적 구체적인 요구 사항이 여전히 있습니다.


4. 기생 생성자 모드(팩토리 모드 + 생성자 모드)

function Box(name, age) {
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	obj.run = function () {
		return this.name + this.age + '运行中...';
	};
	return obj;
}
로그인 후 복사

5. 안전 생성자 모드

function Box(name , age) {
	var obj = new Object();
	obj.run = function () {
		return name + age + '运行中...'; //直接打印参数即可
	};
	return obj;
}
로그인 후 복사

안전 생성자 모드는 생성자, 외부 인스턴스화에서 사용할 수 없는 모드입니다. new를 사용할 수 없는 경우에만 필요합니다.
왜 이렇게 이상한 요구를 하는지 모르겠어요. 그러나 수많은 객체 생성 패턴은 실제로 Java보다 훨씬 더 눈부십니다.

위 내용은 프로토타입을 통한 JavaScript 객체 생성 및 객체 생성 이해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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