객체 생성자 또는 객체 리터럴을 통해 객체를 생성 할 때 동일한 인터페이스로 많은 객체를 생성 할 때 많은 양의 중복 코드가 생성됩니다. 단순화를 위해 공장 모델이 소개되었습니다.
공장 모델
함수 CreatePerson (이름, 나이, 직업) {var obj = new Object (); obj.name = 이름; obj.age = 나이; obj.job = job; obj.sayhello () {alert (this.name); }; return obj;} var p1 = CreatePerson ( "xxyh", 19, "프로그래머"); var p2 = CreatePerson ( "Zhangsan", 18, "Student");객체를 만드는 이러한 방법은 코드를 크게 단순화하지만 단점, 즉 객체의 유형을 결정할 수 없습니다. 이 문제를 해결하기 위해 다음 패턴이 나타납니다.
생성자 모드
사용자 정의 객체 유형의 속성 및 메소드를 정의하기 위해 사용자 정의 생성자를 만듭니다.
기능인 (이름, 나이, 직업) {this.name = 이름; this.age = age; this.job = job; this.sayname = function () {alert (this.name); };} var p1 = 새로운 사람 ( "xxyh", 19, "프로그래머"); var p2 = 새로운 사람 ( "잭", 18, "학생");위의 예에서는 Person ()이 CreatePerson ()을 대체합니다. 또한 몇 가지 차이점이 있습니다.
• 디스플레이없이 객체를 만듭니다.
•이 객체에 속성과 메소드를 직접 할당하십시오
• 반환 명세서가 없습니다
사람 객체를 만들려면 새 연산자를 사용해야합니다. 4 단계로 나뉩니다.
• 새 개체를 만듭니다
• 생성자의 범위를 새 개체에 할당
• 생성자에서 코드를 실행합니다
• 새 개체를 반환하십시오
P1과 P2는 각각 사람의 인스턴스를 저장합니다.
경고 (p1.constructor == person); // truealert (p2.constructor == person); // 진실
유형을 감지 할 때 인스턴스를 사용하는 것이 가장 좋습니다.
경고 (P1 인스턴스 객체); // truealert (p1 인스턴스); // truealert (p2 인스턴스 객체); // truealert (p2 인스턴스); // truealert (p2 인스턴스); // 진실
P1과 P2는 모든 물체가 물체에서 상속되기 때문에 물체의 인스턴스입니다.
2.1 생성자를 기능으로 처리하십시오
// var person = new Person ( "xxyh", 19, "프로그래머"); person.sayname (); // "xxyh"// 일반 함수 사람으로 사용합니다 ( "Zhangsan", 18, "Student"); // windowwindow.sayName ()에 추가합니다. // "Zhangsan"// 다른 객체의 범위에서 var obj를 호출합니다. obj = new Object (); person.call (obj, "jack", 29, "manager"); obj.sayname (); // "Jack", OBJ에는 모든 속성과 방법이 있습니다
2.2 생성자 문제
생성자를 사용하는 데있어 문제는 각 방법이 각 인스턴스에서 다시 만들어야한다는 것입니다. P1과 P2는 모두 sayname () 메소드를 가지고 있지만 함수 인스턴스는 아닙니다. JavaScript에서 함수는 객체이므로 함수가 정의 될 때마다 객체가 인스턴스화됩니다.
생성자는 다음과 같이 정의 할 수 있습니다.
기능인 (이름, 나이, 직업) {this.name = 이름; this.age = age; this.job = job; this.sayname = new 함수 ( "alert (this.name)";}따라서 다른 인스턴스에서 동일한 이름의 기능은 동일하지 않습니다.
경고 (p1.sayname == p2.sayname); // 거짓
그러나 동일한 함수로 두 가지 함수를 만드는 것은 중복되며 코드를 실행하기 전에 기능을 특정 객체에 바인딩 할 필요가 없습니다.
기능인 (이름, 나이, 직업) {this.name = 이름; this.age = age; this.job = job; this.sayname = sayname;} 함수 sayname () {alert (this.name);} var p1 = new Person ( "xxyh", 19, "프로그래머"); var p2 = new Person ( "Jack", 18, "Student");위는 생성자 외부에서 sayname ()의 정의를 이동시킨 다음 속성 sayname을 생성자 내부의 글로벌 SayName 함수로 설정합니다. 이러한 방식으로 SayName은 함수에 대한 포인터를 포함하고 P1과 P2는 전역 범위에 정의 된 동일한 SayName () 함수를 공유합니다.
그러나 여기에는 새로운 문제가 있습니다. 글로벌 범위에 정의 된 기능은 특정 객체 만 호출 할 수 있습니다. 객체가 많은 방법을 정의하면 참조 유형이 캡슐화를 잃습니다.
프로토 타입 체인 모드
각 함수에는 프로토 타입 속성이 있으며, 이는 객체를 가리키는 포인터입니다. 이 객체의 목적은 특정 유형의 모든 인스턴스에서 공유 할 수있는 속성 및 메소드를 포함하는 것 입니다. 프로토 타입은 생성자를 호출하여 생성 된 해당 객체 인스턴스의 프로토 타입 객체입니다. 프로토 타입 객체를 사용하는 장점은 모든 객체 인스턴스가 포함 된 속성과 메소드를 공유 할 수 있다는 것입니다. 이는 생성자에서 객체 인스턴스의 정보를 정의하는 대신이 정보가 프로토 타입 객체에 추가됨을 의미합니다.
function person () {} person.prototype.name = "xxyh"; person.prototype.age = 19; person.prototype.job = "programmer"; person.prototype.sayname = function () {alert (this.name); var person1 = new person (); person1.sayname (); // "xxyh"var person2 = new Person (); person.2.sayname (); // "xxyh"alert (person1.sayname == person2.sayname); // 진실3.1 프로토 타입 객체 이해
새 기능 만 만들면 기능에 대한 프로토 타입 속성이 생성되며 기능의 프로토 타입 객체를 가리 킵니다. 기본적으로 모든 프로토 타입 객체는 생성자 특성을 자동으로 얻습니다. 이 속성에는 프로토 타입 속성이있는 기능에 대한 포인터가 포함되어 있습니다. person.prototype.constructor는 사람을 가리 킵니다.
생성자가 인스턴스를 생성하기 위해 호출되면 인스턴스 내부에는 [[프로토 타입]이라는 생성자의 프로토 타입 객체에 대한 포인터 (내부 특성)가 포함됩니다. Firefox, Safari 및 Chrome에서 _proto를 통해 액세스합니다. 이 연결은 인스턴스와 생성자 사이가 아닌 인스턴스와 생성자의 프로토 타입 객체 사이에 존재합니다.
다음 그림은 각 객체 간의 관계를 보여줍니다.
person.prototype 프로토 타입 객체를 가리키고 person.prototype.constructor는 사람을 가리 킵니다. 생성자 속성 외에도 프로토 타입에는 다른 추가 된 속성이 있습니다. 개인 인스턴스에는 모두 Person.prototype 만 가리키는 내부 속성을 포함하며 생성자와 직접적인 관계가 없습니다.
[[프로토 타입]]에 액세스 할 수는 없지만 isprototype () 방법을 사용하여 객체간에 그러한 관계가 있는지 여부를 결정할 수 있습니다.
Alert (person.prototype.isprototypof (person1)); // truealert (person.prototype.isprototypof (person2)); // 진실
객체의 속성을 읽을 때, 주어진 이름의 속성의 목표와 함께 검색이 수행됩니다. 검색은 객체 인스턴스 자체로 시작합니다. 검색은 객체 인스턴스 자체에서 시작됩니다. 주어진 이름이있는 속성이 인스턴스에있는 경우 속성의 값이 반환됩니다. 찾을 수없는 경우 포인터가 가리키는 프로토 타입 객체를 계속 검색하고 프로토 타입 객체에 주어진 이름의 속성을 찾으십시오. 이 속성이 프로토 타입 객체에서 발견되면 속성 값이 반환됩니다.
프로토 타입에 저장된 값은 객체 인스턴스를 통해 액세스 할 수 있지만 프로토 타입에 저장된 값은 객체 인스턴스를 통해 다시 작성할 수 없습니다 . 인스턴스 프로토 타입의 속성과 동일한 이름으로 인스턴스에 속성을 추가하면 속성이 프로토 타입의 속성을 차단합니다.
function person () {} person.prototype.name = "xxyh"; person.prototype.age = "20"; person.prototyp.job = "programmer"; person.prototype.sayname = function () {alert (this.name); var person1 = new person (); new person2 = new Person (); name = "ooo," // "OOOO"ALERT (person2.name); // "XXYH"위의 예에서는 Person1의 이름 속성이 프로토 타입의 이름 속성을 차단합니다.
객체 인스턴스에 속성이 추가되면이 속성은 프로토 타입 객체에 저장된 동일한 이름의 속성을 차단합니다. 이는이 속성의 존재가 프로토 타입의 해당 속성에 대한 접근을 방지 할 것임을 의미합니다. 삭제를 사용하여 인스턴스 속성을 삭제하십시오.
function person () {} person.prototype.name = "xxyh"; person.prototype.age = "20"; person.prototyp.job = "programmer"; person.prototype.sayname = function () {alert (this.name); var person1 = new person (); new person2 = new Person (); name = "ooo," // "OOOO"ALERT (person2.name); // "xxyh"delete person1.name; alert (person1.name); // "XXYH"HasownProperty ()는 인스턴스 또는 프로토 타입에 속성이 존재하는지 여부를 감지 할 수 있습니다.
function person () {} person.prototype.name = "xxyh"; person.prototype.age = "20"; person.prototype.job = "programmer"; person.prototyp.sayname = function () {alert (this.name); var person1 = new person (); new person2 = new person2 = new person ()); // falseperson1.name = "oooo"; alert (person1.hasownproperty ( "name")); // 진실다음 그림은 다양한 상황에서 구현과 프로토 타입의 관계를 보여줍니다.
3.2 프로토 타입 및 연산자
IN 연산자를 사용하는 방법 : 단독으로 사용하십시오. 단독으로 사용될 때 인스턴스에 있든 원형에 존재하는지 여부에 관계없이 객체를 통해 주어진 속성에 액세스 할 때 IN 연산자가 TRUE를 반환합니다 .
function person () {} person.prototype.name = "xxyh"; person.prototype.age = "20"; person.prototyp.job = "programmer"; person.prototype.sayname = function () {alert (this.name); var person1 = new person (); "이름"in inter person1); // trueperson1.name = "oooo"; alert (person1의 "name"); // 진실이전 HasownProperty () 기능과 결합하여 속성은 프로토 타입의 속성이거나 인스턴스의 속성임을 결정할 수 있습니다. 운영자가 TRUE를 반환하고 HasOwnProperty가 False를 반환하면 속성은 프로토 타입의 속성입니다.
함수 HASPROTOTYPEPROPERTY (Object, Name) {return! Object.HasOwnProperty (이름) && (객체의 이름);}다음으로 HasprotoTyPeproperty ()의 사용법을 살펴 보겠습니다.
function person () {} person.prototype.name = "xxyh"; person.prototype.age = "20"; person.prototyp.job = "programmer"; person.prototype.sayname = function () {alert (this.name); var person = new person (); // trueperson.name = "oooo"; Alert (hasprotoTypeProperty (person, "name")); // 거짓For-in 루프를 사용하는 경우 인스턴스의 속성 및 프로토 타입의 속성을 포함하여 객체를 통해 액세스 할 수있는 모든 열거 가능한 속성. 프로토 타입에서 발전 할 수없는 데이터를 차단하는 인스턴스 속성 (즉, [[[Enumerable]]]에 의해 False로 표시된 속성)는 규정에 따라 개발자에 의해 정의 된 모든 속성이 열거 될 수 있기 때문에 FER-IN에서 반환됩니다.
객체에서 열거 가능한 모든 인스턴스 속성을 얻으려면 Object.keys () 메소드를 사용할 수 있습니다.
function person () {} person.prototype.name = "xxyh"; person.prototype.age = "20"; person.prototyp.job = "programmer"; person.prototype.sayname = function () {alert (this.name); var keys = object.keys (person.prototype); // 이름, 나이, 직업, saynamevar p1 = new person (); p1.name = "oooo"; p1.age = 15; var p1_keys = object.keys (p1); Alert (p1_keys); // 이름, 나이모든 인스턴스 속성을 가져와야하는 경우 객체를 사용할 수 있습니다.
var keys = object.getOwnPropertyNames (person.prototype); Alert (키); // "생성자, 이름, 나이, 직업, SayName"
3.3 더 간단한 프로토 타입 구문
입력을 간소화하려면 모든 특성과 메소드가 포함 된 객체 문자로 통합 프로토 타입 객체를 대체하십시오.
function person () {} person.prototype = {name : "xxyh", 나이 : 18, 직업 : "프로그래머", sayname : function () {alert (this.name); }};상기는 객체 문자 그럴 형식으로 생성 된 새로운 객체와 동일하게 person.prototype를 세트합니다. 결과는 동일하지만 생성자 속성은 더 이상 사람을 가리키지 않습니다.
올바른 결과는 인스턴스를 통해 반환 될 수 있지만 생성자는 객체의 유형을 결정할 수 없습니다.
var boy = new person (); Alert (Boy instanceof Object); // truealert (소년 인스턴스 사람); // truealert (boy.constructor == person); // falSealert (boy.constructor == Object); // 진실
생성자 값은 다음과 같은 방식으로 설정할 수 있습니다.
function person () {} person.prototype = {생성자 : 사람, 이름 : "xxyh", 나이 : 18, 직업 : "프로그래머", sayname : function () {alert (this.name); }};3.4 프로토 타입 체인의 역 동성
프로토 타입에서 값을 찾는 프로세스는 검색이므로 프로토 타입 객체에 대한 수정은 인스턴스에 반영됩니다. 그러나 전체 프로토 타입 객체가 다시 작성되면 결과가 다릅니다. 생성자를 호출 할 때 원래 프로토 타입에 대한 [[[프로토 타입]] 포인터를 인스턴스에 추가하고 프로토 타입을 다른 물체로 수정하는 것은 생성자와 원래 프로토 타입 사이의 연결을 절단하는 것과 같습니다. 인스턴스의 포인터는 생성자가 아닌 프로토 타입 만 지적합니다.
function person () {} var boy = new person (); person.prototype = {생성자 : 사람, 이름 : "xxyh", 나이 : 29, 직업 : "프로그래머", sayname : function () {alert (this.name); }}; boy.sayname (); // 오류특정 프로세스는 다음과 같습니다.
위에서 볼 수 있듯이 프로토 타입 객체를 다시 쓰는 것은 기존 프로토 타입과 이전에 기존 객체 인스턴스 간의 연결을 차단합니다. 그들은 원래 프로토 타입을 나타냅니다.
3.5 네이티브 객체의 프로토 타입
모든 기본 참조 유형은 생성자의 프로토 타입에서 방법을 정의합니다. 기본 객체의 프로토 타입을 통해 기본 메소드를 얻을 수있을뿐만 아니라 새로운 방법을 정의 할 수 있습니다.
String.prototype.startSwith = function (text) {return this.indexof (text) == 0;}; var msg = "Good Morning"; Alert (msg.startSwith ( "good")); // 진실3.6 프로토 타입 객체의 문제
프로토 타입 패턴에는 두 가지 문제가 있습니다.
• 기본적으로 동일한 속성 값입니다.
• 프로토 타입의 모든 속성은 인스턴스에서 공유합니다.
아래의 예를 보자 :
function person () {} person.prototype = {생성자 : 사람, 이름 : "xxyh", 나이 : 18, 직업 : "프로그래머", 친구 : [ "zhang san", "li si"], sayname : function () {alert (this.name); }}; var p1 = new person (); var p2 = new person (); p1.friends.push ( "wang wu"); Alert (p1.friends); // Zhang San, Li SI, Wang Wu Alert (P2.Friends); // Zhang San, Li SI, Wang Wu Alert (P1.Friends == P2.Friends); // 진실P1.Friends를 통해 위에 항목이 추가되었습니다. 친구 배열은 직접 존재하기 때문에 propototype에도 p2에 반영됩니다. 그러나 인스턴스에는 일반적으로 자체 속성이 모두 있습니다.
생성자 모드와 프로토 타입 모드를 조합하여 사용하십시오
생성자 모드는 인스턴스 속성을 정의하는 데 사용되며 프로토 타입 모드는 메소드 및 공유 속성을 정의하는 데 사용됩니다. 이러한 방식으로 각 인스턴스에는 자체 인스턴스 속성 사본이 있지만 동시에 메소드에 대한 참조를 공유합니다.
기능인 (이름, 나이, 직업) {this.name = 이름; this.age = age; this.job = job; this.friends = [ "Zhang San", "li si"];} person.prototype = {생성자 : person, sayname : function () {alert (this.name); }} var p1 = 새로운 사람 ( "Xiao Xiao Yihan", 18, "프로그래머"); var p2 = 새로운 사람 ( "Kuiba", 10, "Monster Hunt"); p1.friends.push ( "Wang Wu"); Alert (p1.friends); // Zhang San, Li SI, Wang Wu 's Alert (P2.Friends); // Zhang San, Li Si Alert (p1.friends == p2.Friends); // falsealsealert (p1.sayname == p2.sayname); // 진실위의 예에서, 인스턴스 특성은 생성자에 정의되는 반면, 공유 속성 생성자 및 메소드 SayName ()은 프로토 타입에 정의된다. P1.Friends의 수정은 P2의 결과에 영향을 미치지 않습니다.
동적 프로토 타입 모드
동적 프로토 타입 패턴은 생성자의 모든 정보를 캡슐화하고 생성자의 프로토 타입을 초기화함으로써 생성자와 프로토 타입을 모두 사용하는 이점을 유지합니다. 즉, 존재하는 방법이 효과적인지 확인하여 프로토 타입을 초기화 해야하는지 여부를 결정할 수 있습니다.
기능인 (이름, 연령, 직업) {// 속성 this.name = 이름; this.age = age; this.job = job; // 메소드 if (typeof this.sayName! = "function") {person.prototype.sayName = function () {alert (this.name); }}}이것은 sayname () 메소드가 존재하지 않을 때만 프로토 타입에 추가되며 생성자가 처음으로 요구 될 때만 실행됩니다.
기생 생성자 패턴
이 패턴의 아이디어는 객체를 생성하는 코드를 캡슐화 한 다음 새로 생성 된 객체를 반환하는 기능을 만드는 기능을 만드는 것입니다.
기능인 (이름, 나이) {var obj = new Object (); obj.name = 이름; obj.age = 나이; obj.sayname = function () {alert (this.name); } return obj;} var boy = new Person ( "xxyh", 19, "프로그래머"); boy.sayname ();우선 , 반환 된 객체는 생성자 또는 생성자의 프로토 타입 속성과 관련이 없습니다. 생성자가 반환 한 물체는 생성자 외부에서 생성 된 물체와 다르지 않습니다. 객체 유형을 결정하기 위해 연산자의 인스턴스를 의존 할 수 없습니다.
안정적인 생성자 패턴
안전한 객체는 공개 속성이없는 객체를 말하며 그 방법은이를 참조하지 않습니다. 안정적인 생성자는 기생 생성자와 유사한 패턴을 따르지만 두 가지 차이점이 있습니다.
• 새로 생성 된 객체의 인스턴스 방법은 이것을 언급하지 않습니다.
• 생성자는 새 연산자를 사용하여 호출되지 않습니다
다음과 같이 개인 생성자를 다시 작성하십시오.
기능인 (이름, 연령, 직업) {var obj = new Object (); obj.sayname = function () {alert (name); }; return obj;} 기능인 (이름, 연령, 직업) {var obj = new Object (); obj.sayname = function () {alert (name); }; return obj;}위의 기사는 JavaScript 객체의 생성에 대해 간단히 이야기합니다. 나는 그것이 당신에게 참조를 줄 수 있기를 바랍니다. 그리고 당신이 wulin.com을 더 지원할 수 있기를 바랍니다.