개요
JavaScript의 모든 객체에는 자체 상속 체인이 있습니다. 즉, 각 객체는 "프로토 타입"객체라고하는 다른 객체를 상속합니다. NULL을 제외하고는 자체 프로토 타입 객체가 없습니다.
프로토 타입 객체의 중요성은 객체 A가 객체 B의 프로토 타입 인 경우 객체 B의 모든 특성과 객체 A를 얻을 수 있다는 것입니다. 객체 .GetProtoTypof 메소드는 현재 객체의 프로토 타입 객체를 얻는 데 사용됩니다.
var p = Object.getPrototypof (obj);
위의 코드에서 객체 P는 Object obj의 프로토 타입 객체입니다.
객체. 만족 메소드는 새 객체를 생성하고 지정된 객체를 상속하는 데 사용됩니다.
var obj = object.create (p);
위의 코드에서 새로 생성 된 OBJ 객체의 프로토 타입은 객체 p입니다.
비표준 __proto__ 속성 (앞뒤에 두 개의 밑줄)은 특정 객체의 프로토 타입 객체를 다시 쓸 수 있습니다. 그러나이 속성을 최대한 적게 사용하려고하지만 개체를 사용하여 () 및 Object.setPrototypof ()를 사용하여 프로토 타입 객체를 읽고 쓰십시오.
var obj = {{}; var p = {}; obj .__ proto__ = p; object.getPrototyp (obj) === p // true위의 코드는 p 객체를 __proto__ 속성을 통해 OBJ 객체의 프로토 타입으로 설정합니다.
다음은 실용적인 예입니다.
var a = {x : 1}; var b = {__proto__ : a}; bx // 1위의 코드에서 객체 B는 __proto__ 속성을 통해 프로토 타입 객체를 객체로 설정하므로 객체 B는 객체 a의 모든 속성과 메소드를 얻을 수 있습니다. B 객체 자체에는 x 속성이 없지만 JavaScript 엔진은 __proto__ 속성을 통해 프로토 타입 객체 A를 찾은 다음 a의 x 속성을 읽습니다.
새 명령은 생성자를 통해 새 인스턴스 객체를 만듭니다. 인스턴스 개체의 프로토 타입을 생성자의 프로토 타입 속성에 본질적으로 바인딩 한 다음 인스턴스 객체에서 생성자를 실행합니다.
var o = new foo (); //는 var o = new object (); o .__ proto_ = foo.prototype; foo.call (o);
프로토 타입 객체 자체의 __proto__ 속성은 다른 객체를 가리키하여 "프로토 타입 체인"레벨을 레벨별로 형성 할 수 있습니다.
var a = {x : 1}; var b = {__proto__ : a}; var c = {__proto__ : b}; cx // 1프로토 타입 체인에서 특정 속성을 찾는 것은 성능에 영향을 미칩니다. 원하는 프로토 타입 객체의 레벨이 높을수록 성능에 미치는 영향이 커집니다. 존재하지 않는 속성을 찾으면 전체 프로토 타입 체인을 통과합니다.
이 행동을 가리키는 것
어디에서 정의 되든, 사용하면 항상 프로토 타입 객체가 아닌 현재 객체를 가리 킵니다.
var o = {a : 2, m : 함수 (b) {return this.a + 1; }}; var p = object.create (o); pa = 12; pm () // 13위의 코드에서 P 객체의 M 메소드는 프로토 타입 객체 O에서 나옵니다. 현재 M 메소드 내부 의이 객체는 O를 가리키지 않고 p.
생성자의 상속
이 섹션에서는 하나의 생성자가 다른 생성자를 상속하는 방법을 소개합니다.
모양 생성기가 있다고 가정하십시오.
함수 모양 () {this.x = 0; this.y = 0;} shape.prototype.move = function (x, y) {this.x += x; this.y += y; console.info ( 'shape moved.');}; 사각형 생성자는 모양을 상속합니다. 함수 사각형 () {shape.call (this); // 부모 클래스 생성자를 호출} // 기능을 쓰는 다른 방법 rectangle () {this.base = shape; this.base ();} // 서브 클래스는 상위 클래스 메소드 사각형을 상속합니다. rectangle.prototype = object.create (shape.prototype); rect.prototype.constructor = 사각형; var rect = new Earmangle (); rectinsof rectangle // shape // truerect.move (1, 1) move.위의 코드는 생성자의 상속이 두 부분으로 나뉘어져 있음을 보여줍니다. 하나는 서브 클래스가 부모 클래스의 생성자 메소드를 호출하고, 다른 하나는 서브 클래스의 프로토 타입이 부모 클래스의 프로토 타입을 가리킨다는 것입니다.
위의 코드에서 서브 클래스는 부모 클래스 전체를 상속합니다. 때로는 단일 방법의 상속 만 필요하며 다음 작성 방법을 사용할 수 있습니다.
classb.prototype.print = function () {classa.prototype.print.call (this); // 일부 코드}위의 코드에서 서브 클래스 B의 인쇄 방법은 먼저 부모 클래스 A의 인쇄 방법을 호출 한 다음 자체 코드를 배포합니다. 이것은 부모 클래스 A의 인쇄 방법을 상속하는 것과 같습니다.
__proto__ 속성
__proto__ 속성은 현재 객체의 프로토 타입 객체, 즉 생성자의 프로토 타입 속성을 가리 킵니다.
var obj = new Object (); obj .__ proto__ === object.prototype // trueobj .__ proto__ === obj.constructor.prototype // true
위의 코드는 먼저 새로운 객체 obj, __proto__ 속성을 생성하여 생성자 (Object 또는 OBJ.constructor)의 프로토 타입 속성을 가리키는다. 따라서 두 가지를 비교 한 후에는 true를 반환하십시오.
따라서 인스턴스 객체 OBJ의 프로토 타입 객체를 얻는 세 가지 방법이 있습니다.
위의 세 가지 방법 중 처음 두 가지 방법은 그다지 신뢰할 수 없습니다. 최신 ES6 표준은 브라우저 만 __proto__ 속성을 배포해야하며 다른 환경이 배포되지 않을 수 있다고 규정하고 있습니다. 그러나 프로토 타입 객체를 수동으로 변경할 때 obj.constructor.prototype가 실패 할 수 있습니다.
var p = function () {}; var p = new p (); var c = function () {{}; c.prototype = p; var c = new c (); c.constructor.prototype === p // false위의 코드에서, C 생성자의 프로토 타입 객체는 p로 변경되며, 결과는 c.constructor.prototyp이 왜곡된다. 따라서 프로토 타입 객체를 변경할 때 생성자 속성을 동시에 설정해야합니다.
C. prototype = p; c.prototype.constructor = c; constructor.prototype === p // true
따라서 프로토 타입 객체를 얻으려면 세 번째 오브젝트를 사용하여 프로토 타입 객체를 얻는 것이 좋습니다. 이 방법의 사용은 다음과 같습니다.
var o = new Object (); object.getPrototypo (o) === Object.Prototype // true
Object.getPrototype Method를 사용하여 브라우저가 __proto__ 속성을 지원하는지 여부를 확인할 수 있으며,이 브라우저에서는 지원되지 않습니다.
Object.getPrototype ({__proto__ : null}) === null위의 코드는 객체의 __proto__ 속성을 NULL로 설정 한 다음 Object.GetPrototype Method를 사용 하여이 객체의 프로토 타입을 얻으려면 NULL과 동등한 지 여부를 결정합니다. 현재 환경이 __proto__ 속성을 지원하는 경우이 둘의 비교 결과는 사실이어야합니다.
__proto__ 속성을 사용하면 인스턴스 객체의 프로토 타입을 쉽게 설정할 수 있습니다. 기계, 차량 및 자동차는 기계가 차량의 프로토 타입이고 차량이 자동차의 프로토 타입이며 두 줄의 코드로만 설정할 수있는 세 가지 물체가 있다고 가정합니다.
차량 .__ proto__ = machine; car .__ proto__ = 차량;
다음은 예입니다. 프로토 타입 객체에 정의 된 특성은 각각 __proto_ artribute 및 생성자 .prototype 속성을 통해 읽습니다.
Array.prototype.p = 'abc'; var a = new Array (); a .__ proto __. p // abca.constructor.prototype.p // abc
분명히, __proto__는 조금 더 간결하게 보입니다.
인스턴스 객체가 생성자를 통해 생성되면 인스턴스 개체의 __proto__ 속성은 생성자의 프로토 타입 객체를 자동으로 가리 킵니다.
var f = function () {}; var a = {}; f.prototype = a; var o = new f (); o .__ proto__ === a // true속성 상속
두 가지 유형의 속성이 있습니다. 하나는 객체 자체의 기본 속성이고 다른 하나는 프로토 타입에서 상속 된 상속 된 속성입니다.
물체의 기본 속성
오브젝트 자체의 모든 속성은 Object.GetOwpropertyNames 메소드를 사용하여 얻을 수 있습니다.
Object.getOrpropertyNames (date) // [ "파스", "인수", "UTC", "발신자", "이름", "프로토 타입", "지금", "길이"]]]]]
물체 자체의 특성 중 일부는 열거 가능 (열거 가능)이지만 다른 일부는 열거 할 수 없습니다. 열거 할 수있는 속성 만 얻고 Object.keys 메소드를 사용하십시오.
Object.keys (날짜) // [] hasownProperty ()
HasownProperty 메소드는 부울 값을 반환하여 특정 속성이 객체 자체 또는 프로토 타입 체인에 정의되어 있는지 여부를 결정합니다.
date.hasownproperty ( 'length') // troodate.hasownproperty ( 'tostring') // false
hasownproperty 메소드는 객체 속성을 처리 할 때 프로토 타입 체인을 가로 지르지 않는 JavaScript의 유일한 방법입니다.
객체의 상속 속성
객체로 생성 된 개체는 모든 프로토 타입 객체의 속성을 상속합니다.
var proto = {p1 : 123}; var o = 객체.모든 속성을 얻으십시오
객체에 특정 속성이 있는지 여부를 확인하려면 (자체이든 상속든) IN 연산자를 사용하십시오.
날짜의 "길이"// true "tostring"날짜 // true
객체의 모든 열거 가능한 속성 (자체이든 상속)를 얻으면 For-in 루프를 사용할 수 있습니다.
var o1 = {p1 : 123}; var o2 = 객체.for ... in loop에서 객체의 자체 속성을 얻으려면 hasownproperty 방법을 사용하여 판단 할 수 있습니다.
for (var name in object) {if (object.hasownproperty (name)) { / * 루프 코드 * /}}객체의 모든 속성을 얻으려면 (자체이든 상속되었는지 여부와 열거 가능 여부) 다음 함수를 사용할 수 있습니다.
함수 henheritedPropertyNames (obj) {var props = {}; while (obj) {object.getOwerPropertyNames (obj) .foreach (function (p) {props [p] = true;}); obj = Object.getPrototypof (obj); } return object.getOwnPropertyNames (props);}사용법은 다음과 같습니다.
inheritedPropertyNames (date) // [ "발신자", "생성자", "Tostring", "UTC", "Call", "Parse", "Protople", "__defineSter__", "__lookupsetter__", "Longth", "Argument", "Bind", "__lookupgetter__", "__lookupgetter__" "PropertyisEnumerable", "ValueOf", "Apply", "__DefineGetter__", "Now", "Now", "HasownProperty"]]]]
개체의 사본
객체를 복사하려면 다음 두 가지 작업을 수행해야합니다.
복사 된 객체의 원래 객체와 동일한 프로토 타입 객체가 있는지 확인하십시오.
복사 된 객체의 원래 객체와 동일한 속성을 가지고 있는지 확인하십시오.
다음은 위의 두 지점을 기반으로 작성된 객체를 복사하는 기능입니다.
함수 copyObject (orig) {var copy = object.create (Object.getPrototypof (orig)); CopyownPropertiesfrom (copy, orig); return copy;} 함수 CopyOwnPropertiesfrom (target, source) {object .getownPropertyNames (source) .foreach (function (propkey) {var desc = object.getownPropertyDescriptor (source, propkey); object.defineProperty (target, propkey, desc); 반환 대상;}다중 상속
JavaScript는 여러 상속 기능을 제공하지 않습니다. 즉, 하나의 객체가 동시에 여러 개체를 상속받을 수 없습니다. 그러나이 기능은 해결 방법을 통해 달성 할 수 있습니다.
함수 m1 (prop) {this.hello = prop;} 함수 m2 (prop) {this.world = prop;} 함수 s (p1, p2) {this.base1 = m1; this.base1 (p1); 이 .base2 = m2; this.base2 (p2);} s.prototype = new m1 (); var s = new s (111, 222); s.hello // 111s.world // 222위의 코드에서 서브 클래스는 부모 클래스 M1과 M2를 상속합니다. 물론, 상속 체인의 관점에서 S는 부모 클래스 M1을 하나만 가지고 있지만 S의 인스턴스에서 M1 및 M2의 생성자가 동시에 실행되기 때문에이 두 클래스의 방법을 동시에 상속합니다.