> 웹 프론트엔드 > JS 튜토리얼 > JavaScript 프로그래밍의 프로토타입 개념에 대한 심층적인 이해_기본 지식

JavaScript 프로그래밍의 프로토타입 개념에 대한 심층적인 이해_기본 지식

WBOY
풀어 주다: 2016-05-16 15:53:05
원래의
1135명이 탐색했습니다.

JavaScript의 프로토타입 객체는 항상 혼란스럽습니다. 숙련된 JavaScript 전문가와 작성자조차도 이 개념에 대해 매우 제한적으로 설명하는 경우가 많습니다. 나는 문제가 프로토타입에 대한 우리의 초기 이해에서 비롯된다고 믿습니다. 프로토타입은 항상 new, 생성자 및 혼란스러운 프로토타입 속성과 밀접하게 연관되어 있습니다. 사실 프로토타이핑은 상당히 간단한 개념입니다. 이를 더 잘 이해하려면 우리가 '배운' 건축 원형을 잊어버린 다음 뿌리로 돌아가야 합니다.

프로토타입이란 무엇인가요?

프로토타입은 다른 객체로부터 속성을 상속받는 객체입니다.

모든 객체가 프로토타입이 될 수 있나요?

그 물체에 프로토타입이 있나요?

모든 개체에는 기본 프로토타입이 있습니다. 프로토타입 자체는 객체이며 각 프로토타입 자체에는 프로토타입이 있습니다. (한 가지 예외를 제외하면 기본 객체 프로토타입은 각 프로토타입 체인의 맨 위에 있고 다른 프로토타입은 프로토타입 체인의 끝에 있습니다.)

한발 물러서서 사물이란 무엇인가?

JavaScript에서 객체는 키-값 쌍으로 저장된 임의의 정렬되지 않은 컬렉션입니다. 기본 클래스(정의되지 않음, null, boolean.nuber 또는 문자열)가 아닌 경우 객체입니다.

각 객체에는 프로토타입이 있다고 생각하실 수 있습니다. 그런데 ({}).prototype을 작성해보니 정의되지 않은 상태가 됐습니다.

프로토타입 속성에 대해 알고 있는 모든 것을 잊어버리세요. 이는 아마도 혼란의 원인일 것입니다. ECMA 5에서는 표준 액세스 방법인 Object.getPrototypeOf(object )가 도입되었습니다. . 이 최신 구현은 Firefox, Safari, Chrome 및 IE9에서 지원됩니다. 또한 IE를 제외한 모든 브라우저는 비표준 액세스 방법인 __proto__를 지원합니다. 그렇지 않으면 개체의 생성자가 해당 프로토타입 속성이라고 말할 수 있습니다.

var a = {};
 
//Opera 或 IE<=8下失败
Object.getPrototypeOf(a); //[object Object]
 
//IE下失败
a.__proto__; //[object Object]
 
//所有浏览器
//(but only if constructor.prototype has not been replaced and fails with Object.create)
a.constructor.prototype; //[object Object]
로그인 후 복사


아주 좋습니다. false는 기본 유형입니다. false.__proto__가 값을 반환하는 이유는 무엇인가요?

기본 유형의 프로토타입에 액세스하면 객체로 강제 변환됩니다.

//(works in IE<=8 too, due to double-negative)
false.__proto__ === Boolean(false).__proto__; //true
로그인 후 복사

프로토타입을 이용하여 상속을 구현하고 싶은데 어떻게 해야 하나요?

인스턴스에 프로토타입 속성을 추가하는 것은 거의 의미가 없습니다. 즉, 이미 객체가 있고 기존 객체를 공유하고 싶다고 가정하면 인스턴스 자체에 직접 속성을 추가하는 것이 매우 효율적입니다. .예를 들어 배열을 사용하면

//fails in IE<=8
var a = {};
a.__proto_ = Array.prototype;
a.length; //0
로그인 후 복사

그러나 프로토타입의 진정한 힘은 동일한 프로토타입을 공유하는 여러 사례에 있다는 것을 알 수 있습니다. 프로토타입 객체의 속성은 한 번 정의되면 해당 객체가 참조하는 모든 인스턴스에 상속됩니다. 프로토타입을 사용하면 성능과 프로그램 유지 관리성이 향상되는 것이 분명합니다. 이것이 생성자의 이유입니까? 예, 생성자는 인스턴스 생성 시 공통 프로토타입 할당을 위한 편리한 크로스 브라우저 메커니즘을 제공합니다. .


예를 들기 전에 constructor.prototype 속성이 무엇을 하는지 알아야 겠죠?

우선 JavaScript는 생성자와 다른 메소드를 구별하지 않기 때문에 모든 메소드에는 프로토타입 속성이 있습니다. 반대로 메소드가 아닌 것은 그러한 속성을 갖지 않습니다.

//永远不是构造函数的方法,无论如何都是有prototype属性的
Math.max.prototype; //[object Object]
 
//构造函数也有prototype属性
var A = function(name) {
  this.name = name;
}
A.prototype; //[object Object]
 
//Math不是一个方法,所以没有prototype属性
Math.prototype; //null
로그인 후 복사

이제 다음을 정의할 수 있습니다. 메소드의 프로토타입 속성은 이 메소드가 인스턴스를 생성하기 위한 생성자로 사용될 때 인스턴스에 할당되는 프로토타입 객체입니다.

메서드의 프로토타입 속성은 실제 프로토타입과 아무런 관련이 없다는 점을 이해하는 것이 매우 중요합니다.

//(在IE中会失败)
var A = function(name) {
  this.name = name;
}
 
A.prototype == A.__proto__; //false
A.__proto__ == Function.prototype; //true - A的prototype是它的构造函数的prototype属性
로그인 후 복사

예를 들어주실 수 있나요?

다음 코드를 수백 번 보거나 사용해 보셨을 수도 있지만, 이번에도 그렇지만 새로운 내용이 있을 수도 있습니다.

//构造器. <em>this</em> 作为新对象返回并且它内部的[[prototype]]属性将被设置为构造器默认的prototype属性
var Circle = function(radius) {
  this.radius = radius;
  //next line is implicit, added for illustration only
  //this.__proto__ = Circle.prototype;
}
 
//扩充 Circle默认的prototype对象的属性因此扩充了每个由它新建实例的prototype对象的属性
Circle.prototype.area = function() {
  return Math.PI*this.radius*this.radius;
}
 
//创建Circle的两个示例,每个都会使用相同的prototype属性
var a = new Circle(3), b = new Circle(4);
a.area().toFixed(2); //28.27
b.area().toFixed(2); //50.27
로그인 후 복사

멋지네요. 생성자의 프로토타입 속성을 변경하면 기존 인스턴스 객체도 새 프로토타입 버전에 즉시 액세스할 수 있나요?

흠... 그렇지는 않네요. 기존 프로토타입의 속성을 수정하는 경우 a.__proto__는 객체가 생성될 때 A.prototype에 의해 정의된 객체를 참조하기 때문에 실제로 그렇습니다.

var A = function(name) {
  this.name = name;
}
 
var a = new A('alpha');
a.name; //'alpha'
 
A.prototype.x = 23;
 
a.x; //23
로그인 후 복사


그러나 프로토타입 속성을 새 객체로 바꾸면 a.__proto__는 여전히 원래 객체를 가리킵니다.

var A = function(name) {
  this.name = name;
}
 
var a = new A('alpha');
a.name; //'alpha'
 
A.prototype = {x:23};
 
a.x; //null
로그인 후 복사

기본 프로토타입은 어떤 모습인가요?

생성자 속성을 가진 객체입니다.

var A = function() {};
A.prototype.constructor == A; //true
 
var a = new A();
a.constructor == A; //true (a 的constructor属性继承自它的原型)
로그인 후 복사


instanceof와 프로토타입은 어떤 관계인가요?
A의 프로토타입 속성이 a의 프로토타입 체인에 나타나면 A 인스턴스의 표현식이 true를 반환합니다. 이는 인스턴스를 실패하도록 속일 수 있음을 의미합니다.

var A = function() {}
 
var a = new A();
a.__proto__ == A.prototype; //true - so instanceof A will return true
a instanceof A; //true;
 
//mess around with a's prototype
a.__proto__ = Function.prototype;
 
//a's prototype no longer in same prototype chain as A's prototype property
a instanceof A; //false
로그인 후 복사


那么我还能利用原型干些其它的什么事儿?

记得我曾经说过每一个构造器都拥有一个prototype属性,利用该属性可以将原型赋值给所有由构造器产生的实例?其实这同样适用于本地构造器,例如Function和String。通过扩展(而不是替换)这个属性,我们可以更新每个指定类型对象的prototype。

String.prototype.times = function(count) {
  return count < 1 &#63; '' : new Array(count + 1).join(this);
}
 
"hello!".times(3); //"hello!hello!hello!";
"please...".times(6); //"please...please...please...please...please...please..."
로그인 후 복사

告诉我更多关于继承与原型是怎么工作的。原型链又是什么东东?


因为每个对象和每个原型(本身)都有一个原型,我们可以想象, 一个接一个的对象连接在一起形成一个原型链。 原型链的终端总是默认对象(object)的原型。

a.__proto__ = b;
b.__proto__ = c;
c.__proto__ = {}; //默认对象
{}.__proto__.__proto__; //null
로그인 후 복사


原型继承机制是内在且隐式实现的。当对象a要访问属性foo时,Javascript会遍历a的原型链(首先从a自身开始),检查原型链的每一个环节中存在的foo属性。如果找到了foo属性就会将其返回,否则返回undefined值。

直接赋值会咋样?

当直接为对象属性赋值时,原型继承机制就玩不转了。a.foo='bar'会直接赋值给a的foo属性。要想为原型对象的属性赋值,你需要直接定位原型对象的该属性。
关于javascript原型就讲全了。我觉得对于原型概念的理解,我把握的还是比较准确的,但是我的观点无论如何也不是最后的结果。请随便告之我的错误之处或提出和我不一致的观点。

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