JavaScript .protype은 어떻게 동작합니까?
나는 동적 프로그래밍 언어에 그다지 관심이 없지만 자바스크립트 코드를 꽤 많이 작성했다.저는 이 프로토타입 기반 프로그래밍에 대해 제대로 이해하지 못했습니다. 어떻게 작동하는지 아는 사람 있나요?
var obj = new Object();
obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();
예전에 사람들과 많은 토론을 했던 기억이 있지만(내가 무엇을 하고 있는지 정확히는 잘 모르겠다), 내가 이해하기로는 수업이라는 개념은 없다.그냥 개체일 뿐이고, 이러한 개체의 인스턴스는 원래 개체의 복제본입니다.
그러나 JavaScript에서 이 ".protype" 속성의 정확한 목적은 무엇입니까?오브젝트 인스턴스화와 어떤 관계가 있습니까?
업데이트: 올바른 방법
var obj = new Object(); // not a functional object
obj.prototype.test = function() { alert('Hello?'); }; // this is wrong!
function MyObject() {} // a first class functional object
MyObject.prototype.test = function() { alert('OK'); } // OK
또한 이 슬라이드는 많은 도움이 되었습니다.
Java, C# 또는 C++와 같은 기존 상속을 구현하는 언어에서는 먼저 클래스(객체의 Blueprint)를 만든 다음 해당 클래스에서 새 개체를 만들거나 클래스를 확장하여 원래 클래스를 추가하는 새 클래스를 정의할 수 있습니다.
JavaScript에서는 먼저 개체를 만든 다음(클래스의 개념은 없음) 자신의 개체를 추가하거나 개체에서 새 개체를 만들 수 있습니다.어려운 일은 아니지만, 조금 이질적이고 신진대사가 어렵습니다.
예:
//Define a functional object to hold persons in JavaScript
var Person = function(name) {
this.name = name;
};
//Add dynamically to the already defined object a new getter
Person.prototype.getName = function() {
return this.name;
};
//Create a new object of type Person
var john = new Person("John");
//Try the getter
alert(john.getName());
//If now I modify person, also John gets the updates
Person.prototype.sayMyName = function() {
alert('Hello, my name is ' + this.getName());
};
//Call the new method on john
john.sayMyName();
지금까지는 기본 오브젝트를 확장해 왔지만, 다른 오브젝트를 작성한 후 Person에서 상속합니다.
//Create a new object of type Customer by defining its constructor. It's not
//related to Person for now.
var Customer = function(name) {
this.name = name;
};
//Now I link the objects and to do so, we link the prototype of Customer to
//a new instance of Person. The prototype is the base that will be used to
//construct all new instances and also, will modify dynamically all already
//constructed objects because in JavaScript objects retain a pointer to the
//prototype
Customer.prototype = new Person();
//Now I can call the methods of Person on the Customer, let's try, first
//I need to create a Customer.
var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();
//If I add new methods to Person, they will be added to Customer, but if I
//add new methods to Customer they won't be added to Person. Example:
Customer.prototype.setAmountDue = function(amountDue) {
this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function() {
return this.amountDue;
};
//Let's try:
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());
var Person = function (name) {
this.name = name;
};
Person.prototype.getName = function () {
return this.name;
};
var john = new Person("John");
alert(john.getName());
Person.prototype.sayMyName = function () {
alert('Hello, my name is ' + this.getName());
};
john.sayMyName();
var Customer = function (name) {
this.name = name;
};
Customer.prototype = new Person();
var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();
Customer.prototype.setAmountDue = function (amountDue) {
this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function () {
return this.amountDue;
};
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());
앞서 말한 바와 같이 setAmountDue()를 호출할 수 없지만 개인에서 getAmountDue()를 호출합니다.
//The following statement generates an error.
john.setAmountDue(1000);
모든 JavaScript 개체에는 다음과 같은 이름의 내부 "슬롯"이 있습니다.[[Prototype]]
그 가치는null
또는object
슬롯은 JavaScript 엔진 내부의 오브젝트상의 속성으로, 작성한 코드로부터 숨겨져 있다고 생각할 수 있습니다.대괄호 둘레[[Prototype]]
는 의도적으로 내부 슬롯을 나타내기 위한 ECMAScript 사양 표기법입니다.
가 지적한 값[[Prototype]]
는 일반적으로 "그 객체의 원형"으로 알려져 있습니다.
점을 통해 자산에 액세스하는 경우(obj.propName
또는 괄호(obj['propName']
( ) 표기법 및 오브젝트는 이러한 속성(즉, 자신의 속성, 확인 가능)을 직접 가지고 있지 않습니다.obj.hasOwnProperty('propName')
런타임은 에 의해 참조되는 개체에서 해당 이름을 가진 속성을 검색합니다.[[Prototype]]
대신.이 경우,[[Prototype]]
또한 이러한 속성을 가지고 있지 않습니다.[[Prototype]]
차례대로 체크하는 등, 계속됩니다.이렇게 하면 원래 물체의 원형 체인은 일치하는 것을 찾거나 그 끝에 도달할 때까지 걷습니다.시제품 체인의 맨 위에는null
가치.
최신 JavaScript 구현으로 인해[[Prototype]]
다음과 같은 방법으로 대응합니다.
- 그
new
연산자(컨스트럭터 함수에서 반환된 기본 객체에 프로토타입 체인을 구성합니다), - 그
extends
키워드(클래스 구문을 사용할 때 프로토타입 체인을 설정합니다), Object.create
지정된 인수를 로 설정합니다.[[Prototype]]
결과 객체의Object.getPrototypeOf
그리고.Object.setPrototypeOf
(취득/설정)[[Prototype]]
오브젝트 작성 후) 및- 표준화된 접근자(getter/setter) 속성 이름:
__proto__
(4와 유사)
Object.getPrototypeOf
그리고.Object.setPrototypeOf
보다 바람직하다__proto__
부분적으로는 의 동작에 의해o.__proto__
물체에 시제품이 있을 때는 이례적이다null
.
오브젝트의[[Prototype]]
는 오브젝트 작성 중에 최초로 설정됩니다.
다음을 통해 새 개체를 만드는 경우new Func()
오브젝트의[[Prototype]]
디폴트로는 에 의해 참조되는 객체로 설정됩니다.Func.prototype
.
따라서 연산자와 함께 사용할 수 있는 모든 클래스와 함수는 자체 내부 슬롯 외에 이름이 붙은 속성을 가집니다."프로토타입"이라는 단어의 이중 사용은 그 언어를 처음 접하는 사람들 사이에서 끝없는 혼란의 원천이다.
사용.new
컨스트럭터 함수를 사용하여 JavaScript에서 기존 상속을 시뮬레이션할 수 있습니다. JavaScript의 상속 시스템은 이미 살펴본 바와 같이 프로토타입이며 클래스 베이스가 아닙니다.
JavaScript에 클래스 구문이 도입되기 전에는 생성자 함수가 클래스를 시뮬레이션하는 유일한 방법이었다.생성자 함수의 함수에 의해 참조되는 객체의 속성을 생각할 수 있습니다..prototype
공유 멤버로서의 속성, 즉 각 인스턴스에서 동일한 멤버.클래스 베이스 시스템에서는 메서드는 각 인스턴스에 대해 동일한 방법으로 구현되므로 메서드는 개념적으로.prototype
그러나 개체의 필드는 인스턴스별로 다르므로 구성 중에 개체 자체에 추가됩니다.
클래스 구문을 사용하지 않으면 개발자는 기존 상속과 유사한 기능을 구현하기 위해 프로토타입 체인을 수동으로 구성해야 했습니다.그 결과, 이것을 실현하기 위한 다양한 방법이 우세하게 되었습니다.
한 가지 방법이 있습니다.
function Child() {}
function Parent() {}
Parent.prototype.inheritedMethod = function () { return 'this is inherited' }
function inherit(child, parent) {
child.prototype = Object.create(parent.prototype)
child.prototype.constructor = child
return child;
}
Child = inherit(Child, Parent)
const o = new Child
console.log(o.inheritedMethod()) // 'this is inherited'
...그리고 또 다른 방법이 있습니다.
function Child() {}
function Parent() {}
Parent.prototype.inheritedMethod = function () { return 'this is inherited' }
function inherit(child, parent) {
function tmp() {}
tmp.prototype = parent.prototype
const proto = new tmp()
proto.constructor = child
child.prototype = proto
return child
}
Child = inherit(Child, Parent)
const o = new Child
console.log(o.inheritedMethod()) // 'this is inherited'
ES2015에서 도입된 클래스 구문은 다음을 제공함으로써 모든 것을 단순화합니다.extends
JavaScript에서 기존 상속을 시뮬레이션하기 위해 프로토타입 체인을 구성하는 "하나의 진정한 방법"으로 사용됩니다.
위의 코드와 마찬가지로 클래스 구문을 사용하여 다음과 같은 새 개체를 만들 경우:
class Parent { inheritedMethod() { return 'this is inherited' } }
class Child extends Parent {}
const o = new Child
console.log(o.inheritedMethod()) // 'this is inherited'
...결과 객체의[[Prototype]]
의 인스턴스로 설정되다Parent
,누구의.[[Prototype]]
그리고, 또,Parent.prototype
.
마지막으로 다음 방법으로 새 개체를 만드는 경우Object.create(foo)
, 결과 오브젝트의[[Prototype]]
로 설정되다foo
.
이는 매우 단순한 프로토타입 기반 객체 모델로 설명 중에 샘플로 간주되며, 아직 아무런 설명도 없습니다.
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
console.log(this.name);
}
var person = new Person("George");
시제품 컨셉을 검토하기 전에 고려해야 할 몇 가지 중요한 사항이 있습니다.
1- JavaScript 함수의 실제 작동 방식:
첫 번째 단계를 진행하려면 JavaScript가 실제로 어떻게 기능하는지 파악해야 합니다.클래스라이크 함수로서 키워드를 사용하는지, 또는 인수와 함께 일반 함수로서 기능하는 것, 동작하는 것, 반환하는 것을 파악해야 합니다.
예를 들어, 이 명령어를Person
오브젝트 모델이 단계에서는 키워드를 사용하지 않고 동일한 작업을 수행하려고 합니다.
이 순서와 키워드로 알 수 있는 것은 이것뿐입니다.
첫 번째 질문은 키워드를 사용하지 않고 키워드를 사용하는 방법입니다.
이 질문에 답하기 위해 빈 객체가 있고 다음과 같은 두 가지 기능이 있다고 가정합니다.
var person = {};
function Person(name){ this.name = name; }
function getName(){
console.log(this.name);
}
키워드를 사용하지 않고 이러한 기능을 사용할 수 있습니다.이를 위해 JavaScript에는 3가지 다른 방법이 있습니다.
a. 첫 번째 방법은 함수를 일반 함수로 호출하는 것입니다.
Person("George");
getName();//would print the "George" in the console
이 경우, 이것은 현재 컨텍스트 오브젝트가 됩니다.이것은 보통 글로벌입니다.window
오브젝트 또는GLOBAL
에Node.js
즉, 브라우저의 window.name 또는 Node.js의 GLOBAL.name에서 "George"를 값으로 사용할 수 있습니다.
b. 우리는 그것들을 물체에 속성으로 부착할 수 있다.
- 가장 쉬운 방법은 빈칸을 수정하는 것입니다.person
오브젝트:
person.Person = Person;
person.getName = getName;
이렇게 부르면 다음과 같습니다.
person.Person("George");
person.getName();// -->"George"
그리고 지금은person
오브젝트는 다음과 같습니다.
Object {Person: function, getName: function, name: "George"}
오브젝트에 속성을 부가하는 다른 방법은prototype
이름을 가진 자바스크립트 객체에서 찾을 수 있는 객체의__proto__
그리고 요약 부분에서 조금 설명하려고 노력했습니다.따라서 다음과 같은 방법으로 동일한 결과를 얻을 수 있습니다.
person.__proto__.Person = Person;
person.__proto__.getName = getName;
하지만 이런 식으로 우리가 실제로 하고 있는 것은Object.prototype
리터럴을 사용하여 JavaScript 객체를 작성할 때마다 ( ){ ... }
)을 기준으로 작성됩니다.Object.prototype
즉, 이 오브젝트는 새로 생성된 오브젝트에 어트리뷰트로 부가되기 때문에 이전 코드 스니펫에서와 같이 변경 시 모든 JavaScript 오브젝트가 변경되어 좋은 프랙티스가 아닙니다.그렇다면 현재 가장 좋은 방법은 무엇입니까?
person.__proto__ = {
Person: Person,
getName: getName
};
지금은 다른 물건들은 평화롭지만, 여전히 좋은 방법은 아닌 것 같습니다.따라서 아직 하나의 솔루션이 더 있지만 이 솔루션을 사용하려면 코드 행으로 돌아가야 합니다.person
오브젝트가 생성되었습니다(var person = {};
그럼 다음과 같이 변경합니다.
var propertiesObject = {
Person: Person,
getName: getName
};
var person = Object.create(propertiesObject);
새로운 JavaScript를 만드는 것입니다.Object
접속하다propertiesObject
에게__proto__
기여하다.다음 작업을 수행할 수 있습니다.
console.log(person.__proto__===propertiesObject); //true
하지만 여기서 까다로운 점은 에 정의된 모든 속성에 액세스할 수 있다는 것입니다.__proto__
의 제1레벨에person
object(자세한 내용은 요약 부분을 참조하십시오).
이 두 가지 방법 중 하나를 사용하면 알 수 있듯이this
정확히 가리키다person
물건.
c. JavaScript는 함수를 제공하는 다른 방법을 가지고 있습니다.this
콜을 사용하거나 함수를 호출하기 위해 적용합니다.
apply() 메서드는 지정된 값을 사용하여 함수를 호출하고 배열(또는 배열과 유사한 개체)로 인수를 제공합니다.
그리고.
call() 메서드는 이 값과 인수가 개별적으로 지정된 함수를 호출합니다.
제가 가장 좋아하는 방법으로, 우리는 쉽게 우리의 기능을 다음과 같이 부를 수 있습니다.
Person.call(person, "George");
또는
//apply is more useful when params count is not fixed
Person.apply(person, ["George"]);
getName.call(person);
getName.apply(person);
이 3가지 방법은 .timeout 기능을 파악하기 위한 중요한 초기 단계입니다.
2 - 어떻게new
키워드 작업?
이것은, 을 이해하기 위한 두 번째 단계입니다..prototype
기능성.프로세스 시뮬레이션을 위해 사용하는 것은 다음과 같습니다.
function Person(name){ this.name = name; }
my_person_prototype = { getName: function(){ console.log(this.name); } };
이 파트에서는 자바스크립트가 실행하는 모든 단계를 수행하려고 합니다.new
키워드 및prototype
, 를 사용하는 경우new
키워드를 지정합니다.그래서 우리가 할 때new Person("George")
,Person
함수는 컨스트럭터 역할을 합니다.JavaScript는 다음과 같은 작업을 하나씩 수행합니다.
a. 우선 빈 객체를 만듭니다.기본적으로 다음과 같은 빈 해시입니다.
var newObject = {};
b. JavaScript가 실행하는 다음 단계는 모든 프로토타입 개체를 새로 만든 개체에 첨부하는 것입니다.
우리는 가지고 있다.my_person_prototype
프로토타입 물체와 비슷합니다.
for(var key in my_person_prototype){
newObject[key] = my_person_prototype[key];
}
이는 JavaScript가 프로토타입에 정의된 속성을 실제로 연결하는 방식이 아닙니다.실제 방법은 원형 체인 개념과 관련이 있습니다.
a. & b. 다음 두 가지 절차를 수행하는 대신 동일한 결과를 얻을 수 있습니다.
var newObject = Object.create(my_person_prototype);
//here you can check out the __proto__ attribute
console.log(newObject.__proto__ === my_person_prototype); //true
//and also check if you have access to your desired properties
console.log(typeof newObject.getName);//"function"
이제 우리는 전화할 수 있다.getName
기능하다my_person_prototype
:
newObject.getName();
c. 그러면 그 오브젝트가 컨스트럭터에게 주어집니다.
샘플로 다음과 같이 할 수 있습니다.
Person.call(newObject, "George");
또는
Person.apply(newObject, ["George"]);
그러면 컨스트럭터는 원하는 대로 할 수 있습니다. 왜냐하면 컨스트럭터 안에 있는 이 객체가 바로 방금 만들어진 객체이기 때문입니다.
이제 다른 단계를 시뮬레이션하기 전에 결과를 종료합니다. 개체 {name: "George"}
요약:.
기본적으로 함수에서 새로운 키워드를 사용할 때는 해당 함수를 호출하고 해당 함수는 컨스트럭터 역할을 하기 때문에 다음과 같이 말합니다.
new FunctionName()
JavaScript는 내부적으로 오브젝트, 빈 해시를 만들고 그 오브젝트를 컨스트럭터에게 주면 컨스트럭터는 원하는 것을 할 수 있습니다.왜냐하면 이 컨스트럭터 내의 오브젝트는 함수에 return 스테이트먼트를 사용하지 않았거나 함수가 입력되어 있으면 당연히 그 오브젝트를 얻을 수 있기 때문입니다.return undefined;
기능 본체의 끝에 있습니다.
JavaScript가 객체의 속성을 조회할 때 가장 먼저 해당 객체의 속성을 조회합니다.그리고 보통 이와 같은 비밀 속성이 있는데, 그 속성은 JavaScript가 다음에 보는 것입니다.를 훑어보면 또 다른 JavaScript 오브젝트인 경우 자체 Atribut이 있으며 다음 Atribut이 null이 될 때까지 위아래로 올라갑니다.이 포인트는 JavaScript에서 속성이 null인 유일한 객체입니다.Object.prototype
오브젝트:
console.log(Object.prototype.__proto__===null);//true
JavaScript에서는 상속이 그렇게 동작합니다.
즉, 함수에 프로토타입 속성이 있고 그 속성을 위해 새로 생성된 객체를 JavaScript가 확인한 후 해당 함수의 정보를 볼 수 있습니다..prototype
또한 이 물체는 자체 내부 프로토타입을 가지고 있을 수도 있습니다.기타 등등.
prototype
를 사용하여 클래스를 만들 수 있습니다.사용하지 않으면prototype
그러면 정적이 됩니다.
여기 간단한 예가 있습니다.
var obj = new Object();
obj.test = function() { alert('Hello?'); };
위의 경우 스태틱 펑션콜 테스트를 실시합니다.이 함수는 obj.test를 통해서만 접근할 수 있으며, 여기서 obj는 클래스로 간주할 수 있습니다.
아래 코드와 같이
function obj()
{
}
obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();
obj는 이제 인스턴스화할 수 있는 클래스가 되었습니다.obj 인스턴스는 여러 개 존재할 수 있으며 모두test
기능.
이상, 저의 이해입니다.커뮤니티 위키로 만들고 있습니다.제가 틀릴 경우 사람들이 저를 정정할 수 있도록요.
시제품의 일곱 칸
시로산은 깊은 명상 끝에 파이어폭스 산을 내려왔을 때 그의 마음은 맑고 평화로웠다.
그러나 그의 손은 안절부절못하며 붓을 잡고 다음 메모를 적어두었다.
0) "프로토타입(prototype)"이라고 할 수 있습니다.
시제품의 특성
obj.prototype
다음과 같이 표현되는 원형 내부 특성
[[Prototype]]
ES5에 있습니다.ES5를 통해 취득할 수 있습니다.
Object.getPrototypeOf()
.Firefox는 다음 사이트에서 액세스 할 수 있습니다.
__proto__
속성을 확장으로 설정합니다.ES6에서는 다음 옵션 요건에 대해 설명하겠습니다.__proto__
.
1) 이러한 개념은 다음과 같은 질문에 답하기 위해 존재합니다.
할 때
obj.property
JS는 어디에서.property
?
직관적으로 기존 상속은 속성 검색에 영향을 미칩니다.
2)
__proto__
점을 찍기 위해 사용됩니다..
와 같은 속성 룩업obj.property
..prototype
는 직접 룩업에 사용되지 않습니다.단, 간접적으로만 사용됩니다.__proto__
와 함께 오브젝트 작성 시new
.
조회 순서:
obj
추가된 속성obj.p = ...
또는Object.defineProperty(obj, ...)
- 의 속성
obj.__proto__
- 의 속성
obj.__proto__.__proto__
, 등 - 어느 정도라면
__proto__
이null
,돌아가다undefined
.
이것은 이른바 원형 체인입니다.
피할 수 있다.
로 조사하다.obj.hasOwnProperty('key')
그리고.Object.getOwnPropertyNames(f)
3) 크게 두 가지 방법으로 설정할 수 있습니다.obj.__proto__
:
new
:var F = function() {} var f = new F()
그리고나서
new
설정:f.__proto__ === F.prototype
여기가 바로 그 장소입니다
.prototype
사용됩니다.Object.create
:f = Object.create(proto)
설정:
f.__proto__ === proto
4) 코드:
var F = function(i) { this.i = i }
var f = new F(1)
다음 그림에 대응합니다(일부 그림).Number
생략) :
(Function) ( F ) (f)----->(1)
| ^ | | ^ | i |
| | | | | | |
| | | | +-------------------------+ | |
| |constructor | | | | |
| | | +--------------+ | | |
| | | | | | |
| | | | | | |
|[[Prototype]] |[[Prototype]] |prototype |constructor |[[Prototype]]
| | | | | | |
| | | | | | |
| | | | +----------+ | |
| | | | | | |
| | | | | +-----------------------+ |
| | | | | | |
v | v v | v |
(Function.prototype) (F.prototype) |
| | |
| | |
|[[Prototype]] |[[Prototype]] [[Prototype]]|
| | |
| | |
| +-------------------------------+ |
| | |
v v v
(Object.prototype) (Number.prototype)
| | ^
| | |
| | +---------------------------+
| | |
| +--------------+ |
| | |
| | |
|[[Prototype]] |constructor |prototype
| | |
| | |
| | -------------+
| | |
v v |
(null) (Object)
다음 다이어그램은 여러 언어의 사전 정의된 개체 노드를 보여 줍니다.
null
Object
Object.prototype
Function
Function.prototype
1
Number.prototype
(다음에서 확인하실 수 있습니다.(1).__proto__
구문을 만족시키려면 , 괄호는 필수입니다.)
두 줄의 코드로 작성된 새로운 오브젝트는 다음과 같습니다.
f
F
F.prototype
i
이제 의 속성이 되었습니다.f
왜냐하면 그렇게 할 때:
var f = new F(1)
평가하다F
와 함께this
가치가 있다new
에 할당됩니다.f
.
5) .constructor
보통 에서 온다F.prototype
을 통해.
검색:
f.constructor === F
!f.hasOwnProperty('constructor')
Object.getPrototypeOf(f) === F.prototype
F.prototype.hasOwnProperty('constructor')
F.prototype.constructor === f.constructor
우리가 글을 쓸 때f.constructor
, JavaScript는.
검색:
f
가지고 있지 않다.constructor
f.__proto__ === F.prototype
가지다.constructor === F
그러니 가져가세요
결과f.constructor == F
직감적으로 옳다.F
를 구축하기 위해 사용됩니다.f
예를 들어, 기존 OOP 언어에서와 같이 set 필드를 설정합니다.
6) 프로토타입 체인을 조작하여 고전적인 상속 구문을 얻을 수 있습니다.
ES6에 의해class
그리고.extends
키워드는 대부분 이전에 사용 가능했던 프로토타입 조작 광기에 대한 구문설탕입니다.
class C {
constructor(i) {
this.i = i
}
inc() {
return this.i + 1
}
}
class D extends C {
constructor(i) {
super(i)
}
inc2() {
return this.i + 2
}
}
// Inheritance syntax works as expected.
c = new C(1)
c.inc() === 2
(new D(1)).inc() === 2
(new D(1)).inc2() === 3
// "Classes" are just function objects.
C.constructor === Function
C.__proto__ === Function.prototype
D.constructor === Function
// D is a function "indirectly" through the chain.
D.__proto__ === C
D.__proto__.__proto__ === Function.prototype
// "extends" sets up the prototype chain so that base class
// lookups will work as expected
var d = new D(1)
d.__proto__ === D.prototype
D.prototype.__proto__ === C.prototype
// This is what `d.inc` actually does.
d.__proto__.__proto__.inc === C.prototype.inc
// Class variables
// No ES6 syntax sugar apparently:
// http://stackoverflow.com/questions/22528967/es6-class-variable-alternatives
C.c = 1
C.c === 1
// Because `D.__proto__ === C`.
D.c === 1
// Nothing makes this work.
d.c === undefined
모든 사전 정의된 개체가 없는 간단한 다이어그램:
(c)----->(1)
| i
|
|
|[[Prototype]]
|
|
v __proto__
(C)<--------------(D) (d)
| | | |
| | | |
| |prototype |prototype |[[Prototype]]
| | | |
| | | |
| | | +---------+
| | | |
| | | |
| | v v
|[[Prototype]] (D.prototype)--------> (inc2 function object)
| | | inc2
| | |
| | |[[Prototype]]
| | |
| | |
| | +--------------+
| | |
| | |
| v v
| (C.prototype)------->(inc function object)
| inc
v
Function.prototype
잠시 시간을 내어 다음 동작에 대해 알아보겠습니다.
c = new C(1)
c.inc() === 2
첫 번째 줄 세트c.i
로.1
(4)에 설명된 바와 같이.
두 번째 줄에서는 다음 작업을 수행합니다.
c.inc()
.inc
에서 찾을 수 있습니다.[[Prototype]]
체인:c
->C
->C.prototype
->inc
- Javascript에서 함수를 다음과 같이 호출할 때
X.Y()
, JavaScript는 자동으로 설정됩니다.this
동등하게 하다X
내부Y()
함수 호출!
정확히 같은 논리로 인해d.inc
그리고.d.inc2
.
이 기사 https://javascript.info/class#not-just-a-syntax-sugar에서는 다음 효과에 대해 설명합니다.class
알만한 가치가 있다.그 중 일부는 이 기능이 없으면 달성할 수 없을 수 있습니다.class
키워드(TODO 체크 대상):
[[FunctionKind]]:"classConstructor"
그러면 컨스트럭터가 new로 호출됩니다.ES6 클래스 컨스트럭터를 일반 함수로 호출할 수 없는 이유는 무엇입니까?- 클래스 메서드는 열거할 수 없습니다.할 수 있다
Object.defineProperty
. - 항상 수업
use strict
명시적인 방법으로 실행할 수 있습니다.use strict
모든 기능을 위해 사용할 수 있지만, 이는 분명 지루합니다.
이 스레드를 읽은 후 JavaScript 프로토타입 체인과 혼동되어 이 차트를 찾았습니다.
http://iwiki.readthedocs.org/en/latest/javascript/js_core.html#inheritance
프로토타입 체인에 의한 JavaScript 상속을 보여주는 명확한 차트입니다.
그리고.
http://www.javascriptbank.com/javascript/article/JavaScript_Classical_Inheritance/
이 예에는 코드와 몇 가지 멋진 다이어그램이 포함되어 있습니다.
프로토타입 체인은 최종적으로 Object.protype으로 돌아갑니다.
하위 클래스의 프로토타입을 상위 클래스의 객체와 동일하게 설정하면 매번 프로토타입을 기술적으로 확장할 수 있습니다.
JavaScript 프로토타입 체인을 이해하는 것도 도움이 되길 바랍니다.
모든 오브젝트에는 다른 오브젝트에 링크하는 내부 속성[Protype]이 있습니다.
object [[Prototype]] → anotherObject
기존 Javascript에서 링크된 객체는prototype
함수의 속성:JavaScript .protype은 어떻게 동작합니까?
object [[Prototype]] → aFunction.prototype
환경에 따라서는 [프로토타입]이 다음과 같이 표시됩니다.__proto__
:
anObject.__proto__ === anotherObject
[프로토타입]링크는 오브젝트를 작성할 때 만듭니다.
// (1) Object.create:
var object = Object.create(anotherObject)
// object.__proto__ = anotherObject
// (2) ES6 object initializer:
var object = { __proto__: anotherObject };
// object.__proto__ = anotherObject
// (3) Traditional JavaScript:
var object = new aFunction;
// object.__proto__ = aFunction.prototype
따라서 다음 문장은 동일합니다.
var object = Object.create(Object.prototype);
var object = { __proto__: Object.prototype }; // ES6 only
var object = new Object;
링크 타깃은 실제로 표시되지 않습니다(Object.prototype
)는 새로운 스테이트먼트에 기재되어 있습니다.대신 타깃은 컨스트럭터에 의해 암시됩니다)Object
).
주의:
- 모든 오브젝트에는 [Prototype]라는 링크가 있으며 때로는 __proto_로 표시됩니다.
- 모든 기능에는
prototype
속성, 처음에는 빈 개체를 유지합니다. - new로 작성된 객체는
prototype
제조자의 재산입니다. - 함수가 생성자로 사용되지 않는 경우 함수는
prototype
속성은 사용되지 않습니다. - 컨스트럭터가 필요 없는 경우 대신 Object.create를 사용합니다.
new
.
Javascript는 일반적인 의미의 상속은 없지만 프로토타입 체인이 있습니다.
원형 체인
객체의 구성원을 객체에서 찾을 수 없는 경우 프로토타입 체인에서 찾습니다.체인은 다른 물체로 구성되어 있습니다.특정 인스턴스의 프로토타입에는__proto__
변수.javascript에서는 클래스와 인스턴스의 차이가 없기 때문에 모든 오브젝트에 1개가 있습니다.
프로토타입에 함수/변수를 추가하는 이점은 모든 인스턴스가 아니라 메모리에 한 번만 있어야 한다는 것입니다.
프로토타입 체인은 다른 많은 개체로 구성될 수 있기 때문에 상속에도 유용합니다.
이 글은 길다.그러나 JavaScript 상속의 "프로토픽" 특성에 대한 대부분의 질문은 클리어 될 것입니다.그리고 더 많이.기사 전문을 읽어주세요.
JavaScript는 기본적으로 두 가지 종류의 데이터 유형을 가지고 있습니다.
- 비개체
- 물건들
비개체
다음은 비개체 데이터 유형입니다.
- 스트링
- 번호(NaN 및 Infinity 포함)
- 부울값(true, false)
- 정의되어 있지 않다
이러한 데이터 유형은 연산자 유형을 사용할 때 다음을 반환합니다.
string literal(또는 문자열 리터럴을 포함하는 변수) 유형 === 'string'
type of 5(또는 숫자 리터럴 또는 숫자 리터럴, NaN 또는 무한을 포함하는 변수) === '숫자'
true 유형(또는 false 또는 true 또는 false를 포함하는 변수) === 'true'
정의되지 않은 유형(또는 정의되지 않은 변수 또는 정의되지 않은 변수를 포함하는 변수) === 'dispended'
문자열, 숫자 및 부울 데이터 유형은 개체 및 비 개체로 모두 나타낼 수 있습니다.개체로 표시될 때 해당 유형의 개체는 항상 === '개체'입니다.오브젝트 데이터 타입을 이해하면, 이것에 대해 다시 설명하겠습니다.
물건들
개체 데이터 유형은 두 가지 유형으로 더 나눌 수 있습니다.
- 함수 유형 객체
- 비기능 유형 개체
함수 유형 개체는 type of 연산자와 함께 문자열 'function'을 반환하는 개체입니다.새 연산자를 사용하여 새 개체를 만들 수 있는 모든 사용자 정의 함수 및 개체에 내장된 JavaScript가 이 범주에 속합니다.예를 들면.
- 물건
- 스트링
- 번호
- 부울
- 어레이
- 유형 배열
- RegExp
- 기능.
- 새 연산자를 사용하여 새 개체를 만들 수 있는 다른 모든 기본 제공 개체
- 함수 UserDefinedFunction(){ /*사용자 정의 코드 */ }
따라서 typeof(개체) === typeof(String) === typeof(Number) === typeof(Boolean) === typeof(Array) === typeof(RegExp) === typeof(Function) === typeof(UserDefined Function) === '기능'입니다.
모든 함수 유형 객체는 실제로 내장된 JavaScript 객체 함수(재귀적으로 정의된 함수 객체 포함)의 인스턴스입니다.이러한 오브젝트가 다음과 같이 정의되어 있는 것 같습니다.
var Object= new Function ([native code for object Object])
var String= new Function ([native code for object String])
var Number= new Function ([native code for object Number])
var Boolean= new Function ([native code for object Boolean])
var Array= new Function ([native code for object Array])
var RegExp= new Function ([native code for object RegExp])
var Function= new Function ([native code for object Function])
var UserDefinedFunction= new Function ("user defined code")
앞서 설명한 바와 같이 함수 유형 개체는 새 연산자를 사용하여 새 개체를 추가로 만들 수 있습니다.예를 들어 Object, String, Number, Boolean, Array, RegExp 또는 UserDefinedFunction 유형의 객체는 다음을 사용하여 생성할 수 있습니다.
var a=new Object() or var a=Object() or var a={} //Create object of type Object
var a=new String() //Create object of type String
var a=new Number() //Create object of type Number
var a=new Boolean() //Create object of type Boolean
var a=new Array() or var a=Array() or var a=[] //Create object of type Array
var a=new RegExp() or var a=RegExp() //Create object of type RegExp
var a=new UserDefinedFunction()
이렇게 생성된 개체는 모두 Non Function 유형 개체이며 해당 type of==='object'를 반환합니다.이러한 모든 경우 개체 "a"는 연산자 new를 사용하여 개체를 더 이상 생성할 수 없습니다.그래서 다음과 같은 것은 틀렸다.
var b=new a() //error. a is not typeof==='function'
기본 제공 개체 Math는 typeof==='object'입니다.따라서 새 연산자가 Math 유형의 새 개체를 만들 수 없습니다.
var b=new Math() //error. Math is not typeof==='function'
또한 Object, Array 및 RegExp 함수는 연산자 new를 사용하지 않고도 새 개체를 만들 수 있습니다.하지만 다음 사람들은 그렇지 않다.
var a=String() // Create a new Non Object string. returns a typeof==='string'
var a=Number() // Create a new Non Object Number. returns a typeof==='number'
var a=Boolean() //Create a new Non Object Boolean. returns a typeof==='boolean'
사용자 정의 함수는 특수한 경우입니다.
var a=UserDefinedFunction() //may or may not create an object of type UserDefinedFunction() based on how it is defined.
함수 유형 개체는 새 개체를 만들 수 있으므로 생성자라고도 합니다.
정의 시 모든 생성자/함수(빌트인 또는 사용자 정의)에는 "protype"이라는 속성이 자동으로 지정되며, 이 속성은 기본적으로 개체로 설정됩니다.이 개체 자체에는 기본적으로 생성자/함수를 참조하는 "컨스트럭터"라는 속성이 있습니다.
예를 들어 함수를 정의하는 경우
function UserDefinedFunction()
{
}
팔로잉이 자동으로 발생함
UserDefinedFunction.prototype={constructor:UserDefinedFunction}
이 "프로토타입" 속성은 기능 유형 개체에만 있습니다(Non Function 유형 개체에는 없습니다).
이는 새 개체가 생성되면(새 연산자를 사용하여) 생성자 함수의 현재 프로토타입 개체에서 모든 속성과 메서드를 상속하기 때문입니다. 즉, 새로 생성된 개체에서 생성자 함수의 현재 프로토타입 개체에서 참조되는 개체를 참조하는 내부 참조가 생성되기 때문입니다.
상속된 특성을 참조하기 위해 객체에 작성된 이 "내부 참조"를 객체의 프로토타입이라고 합니다(이 프로토타입은 생성자의 "프로토타입" 속성에 의해 참조되는 객체를 참조하지만 개체와는 다릅니다).오브젝트(함수 또는 비함수)에 대해서는 Object.getProtypeOf() 메서드를 사용하여 취득할 수 있습니다.이 방법을 사용하면 물체의 원형 체인을 추적할 수 있습니다.
또한 생성되는 모든 개체(함수 유형 또는 비함수 유형)에는 생성자 함수의 프로토타입 속성에서 참조되는 개체에서 상속되는 "구성자" 속성이 있습니다.기본적으로 이 "구성자" 특성은 이 속성을 만든 생성자 함수를 참조합니다(생성자 함수의 기본 "프로토타입"이 변경되지 않은 경우).
모든 함수 유형 개체에 대해 생성자 함수는 항상 함수(){}입니다.
Non Function type 객체(예: Javascript Built in Math 객체)의 경우 생성자 함수가 생성자 함수입니다.Math 객체의 경우 함수 Object(){}입니다.
위에서 설명한 모든 개념은 지원 코드 없이 이해하기 어려울 수 있습니다.개념을 이해하려면 다음 코드를 한 줄씩 읽어보십시오.더 잘 이해할 수 있도록 실행해 보세요.
function UserDefinedFunction()
{
}
/* creating the above function automatically does the following as mentioned earlier
UserDefinedFunction.prototype={constructor:UserDefinedFunction}
*/
var newObj_1=new UserDefinedFunction()
alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype) //Displays true
alert(newObj_1.constructor) //Displays function UserDefinedFunction
//Create a new property in UserDefinedFunction.prototype object
UserDefinedFunction.prototype.TestProperty="test"
alert(newObj_1.TestProperty) //Displays "test"
alert(Object.getPrototypeOf(newObj_1).TestProperty)// Displays "test"
//Create a new Object
var objA = {
property1 : "Property1",
constructor:Array
}
//assign a new object to UserDefinedFunction.prototype
UserDefinedFunction.prototype=objA
alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype) //Displays false. The object referenced by UserDefinedFunction.prototype has changed
//The internal reference does not change
alert(newObj_1.constructor) // This shall still Display function UserDefinedFunction
alert(newObj_1.TestProperty) //This shall still Display "test"
alert(Object.getPrototypeOf(newObj_1).TestProperty) //This shall still Display "test"
//Create another object of type UserDefinedFunction
var newObj_2= new UserDefinedFunction();
alert(Object.getPrototypeOf(newObj_2)===objA) //Displays true.
alert(newObj_2.constructor) //Displays function Array()
alert(newObj_2.property1) //Displays "Property1"
alert(Object.getPrototypeOf(newObj_2).property1) //Displays "Property1"
//Create a new property in objA
objA.property2="property2"
alert(objA.property2) //Displays "Property2"
alert(UserDefinedFunction.prototype.property2) //Displays "Property2"
alert(newObj_2.property2) // Displays Property2
alert(Object.getPrototypeOf(newObj_2).property2) //Displays "Property2"
모든 객체의 프로토타입 체인은 최종적으로 Object.protype(프로토타입 자체에는 프로토타입 객체가 없음)으로 추적됩니다.다음 코드를 사용하여 객체의 프로토타입 체인을 추적할 수 있습니다.
var o=Starting object;
do {
alert(o + "\n" + Object.getOwnPropertyNames(o))
}while(o=Object.getPrototypeOf(o))
다양한 물체의 시제품 체인은 다음과 같이 동작합니다.
- 모든 기능 객체(내장 기능 객체 포함)-> 기능.프로토타입 -> 오브젝트.프로토타입 -> 특수한 순서입니다.
- 심플 오브젝트 (새 오브젝트() 또는 {}에 의해 작성됨)-> Object.protype -> null
- 새 개체 또는 Object.create -> 하나 이상의 프로토타입 체인으로 작성된 개체 -> Object.protype -> null
프로토타입 없이 객체를 작성하려면 다음을 사용합니다.
var o=Object.create(null)
alert(Object.getPrototypeOf(o)) //Displays null
컨스트럭터의 프로토타입 속성을 null로 설정하면 null 프로토타입을 가진 오브젝트가 생성된다고 생각할 수 있습니다.그러나 이러한 경우 새로 생성된 객체의 프로토타입은 Object.protype으로 설정되고 생성자는 function Object로 설정됩니다.이는 다음 코드로 확인할 수 있습니다.
function UserDefinedFunction(){}
UserDefinedFunction.prototype=null// Can be set to any non object value (number,string,undefined etc.)
var o=new UserDefinedFunction()
alert(Object.getPrototypeOf(o)==Object.prototype) //Displays true
alert(o.constructor) //Displays Function Object
이 기사의 개요를 다음에 나타냅니다.
- 오브젝트에는 기능유형과 비기능유형이 있습니다.
함수 유형 개체만 연산자 new를 사용하여 새 개체를 만들 수 있습니다.이렇게 생성된 객체는 Non Function 유형 객체입니다.Non Function 유형 개체는 연산자 new를 사용하여 개체를 더 이상 생성할 수 없습니다.
기본적으로 모든 기능 유형 개체에는 "프로토타입" 속성이 있습니다.이 "프로토타입" 속성은 기본적으로 함수 유형 개체 자체를 참조하는 "구성자" 속성을 가진 개체를 참조합니다.
모든 객체(함수 유형 및 비함수 유형)에는 기본적으로 함수 유형 객체/구성자를 참조하는 "구성자" 속성이 있습니다.
내부적으로 작성된 모든 객체는 객체를 작성한 생성자의 "프로토타입" 속성에 의해 참조되는 객체를 참조합니다.이 객체는 생성된 객체의 프로토타입으로 알려져 있습니다(이 객체가 참조하는 기능 유형 객체의 "protype" 속성과는 다릅니다).이렇게 하면 생성된 객체가 생성자의 "프로토타입" 속성에 의해 참조되는 객체에 정의된 메서드 및 속성에 직접 액세스할 수 있습니다(개체 생성 시).
오브젝트의 프로토타입(및 상속된 속성명)은 Object.getProtypeOf() 메서드를 사용하여 취득할 수 있습니다.실제로 이 방법을 사용하여 개체의 전체 프로토타입 체인을 탐색할 수 있습니다.
모든 객체의 프로토타입 체인은 최종적으로 Object.protype으로 추적됩니다(Object.create(null)를 사용하여 객체를 생성하지 않는 경우).
type of ( new Array ) === 'object'는 더글라스 크록포드가 지적한 실수가 아닌 언어의 설계에 의한 것입니다.
컨스트럭터의 프로토타입 속성을 null(또는 defined, number, true, false, string)로 설정해도 null 프로토타입을 가진 오브젝트가 생성되지 않습니다.이 경우 새로 생성된 객체의 프로토타입은 Object.protype으로 설정되고 생성자는 function Object로 설정됩니다.
이게 도움이 됐으면 좋겠다.
프로토타입 체인을 두 가지 범주로 분류하는 데 도움이 될 수 있습니다.
컨스트럭터를 고려합니다.
function Person() {}
가치Object.getPrototypeOf(Person)
함수입니다.사실 그렇습니다.Function.prototype
.부터Person
함수로 생성되었으며 모든 함수가 가지고 있는 동일한 프로토타입 함수 객체를 공유합니다.와 같다.Person.__proto__
단, 이 속성은 사용하지 마십시오.하여튼.Object.getPrototypeOf(Person)
원형 체인으로 불리는 사다리를 효과적으로 올라갑니다.
위쪽 방향의 체인은 다음과 같습니다.
Person
→Function.prototype
→Object.prototype
(종료점)
중요한 것은 이 프로토타입 체인이 그 대상과 거의 관련이 없다는 것입니다.Person
구축할 수 있습니다.이러한 구성된 개체에는 자체 프로토타입 체인이 있으며, 이 체인은 위에서 언급한 것과 공통되는 가까운 조상이 없을 수 있습니다.
다음 개체를 예로 들어 보겠습니다.
var p = new Person();
p는 개인과 직접적인 프로토타입 체인 관계가 없습니다.그들의 관계는 다르다.오브젝트 p에는 자체 시제품 체인이 있습니다.사용.Object.getPrototypeOf
체인은 다음과 같습니다.
p
→Person.prototype
→Object.prototype
(종료점)
이 체인에는 함수 개체가 없습니다(단, 그럴 수도 있습니다).
그렇게Person
자신의 삶을 사는 두 종류의 사슬과 관련이 있는 것 같습니다.하나의 체인으로 다른 체인으로 "점프"하려면 다음을 사용합니다.
.prototype
: 컨스트럭터 체인에서 생성된 오브젝트 체인으로 점프합니다.따라서 이 속성은 함수 개체에 대해서만 정의됩니다.new
기능에서만 사용할 수 있습니다.).constructor
: created-object 체인에서 컨스트럭터 체인으로 점프합니다.
다음은 관련된 두 가지 프로토타입 체인의 시각적 표시로, 열로 표시됩니다.
요약:
그
prototype
속성은 대상의 프로토타입 체인에 대한 정보를 제공하지 않고 대상에 의해 생성된 개체에 대한 정보를 제공합니다.
부동산의 이름이prototype
혼란을 초래할 수 있습니다.이 부동산의 이름을 붙였더라면 더 분명했을지도 모릅니다.prototypeOfConstructedInstances
뭐 그런 식으로요
두 프로토타입 체인 사이를 앞뒤로 이동할 수 있습니다.
Person.prototype.constructor === Person
이 대칭은 다른 개체를 명시적으로 할당함으로써 깨질 수 있습니다.prototype
property(자세한 내용은 나중에 참조).
하나의 함수를 만들고 두 개의 개체를 가져옵니다.
Person.prototype
함수와 동시에 생성된 객체입니다.Person
작성되었습니다.정말 그랬어요.Person
아직 실제로 실행하지 않았음에도 불구하고, 컨스트럭터로서 기능하고 있습니다.따라서 두 개의 개체가 동시에 생성됩니다.
- 함수
Person
그 자체 - 함수를 생성자로 호출할 때 프로토타입으로 작동할 개체
둘 다 오브젝트이지만 역할이 다릅니다.기능 오브젝트는 구성되고 다른 오브젝트는 함수가 구성하는 오브젝트의 프로토타입을 나타냅니다.프로토타입 객체는 프로토타입 체인에서 생성된 객체의 부모가 됩니다.
함수도 객체이기 때문에 자체 프로토타입 체인에 자체 모체도 있지만, 이 두 체인은 서로 다른 것에 관한 것임을 기억하십시오.
다음은 문제를 파악하는 데 도움이 될 수 있는 몇 가지 균등성입니다.true
:
function Person() {};
// This is prototype chain info for the constructor (the function object):
console.log(Object.getPrototypeOf(Person) === Function.prototype);
// Step further up in the same hierarchy:
console.log(Object.getPrototypeOf(Function.prototype) === Object.prototype);
console.log(Object.getPrototypeOf(Object.prototype) === null);
console.log(Person.__proto__ === Function.prototype);
// Here we swap lanes, and look at the constructor of the constructor
console.log(Person.constructor === Function);
console.log(Person instanceof Function);
// Person.prototype was created by Person (at the time of its creation)
// Here we swap lanes back and forth:
console.log(Person.prototype.constructor === Person);
// Although it is not an instance of it:
console.log(!(Person.prototype instanceof Person));
// Instances are objects created by the constructor:
var p = new Person();
// Similarly to what was shown for the constructor, here we have
// the same for the object created by the constructor:
console.log(Object.getPrototypeOf(p) === Person.prototype);
console.log(p.__proto__ === Person.prototype);
// Here we swap lanes, and look at the constructor
console.log(p.constructor === Person);
console.log(p instanceof Person);
프로토타입 체인에 레벨 추가
생성자 함수를 만들 때 프로토타입 개체가 생성되더라도 해당 개체를 무시하고 해당 생성자에 의해 생성된 이후 인스턴스의 프로토타입으로 사용해야 하는 다른 개체를 할당할 수 있습니다.
예:
function Thief() { }
var p = new Person();
Thief.prototype = p; // this determines the prototype for any new Thief objects:
var t = new Thief();
이제 t의 원형 체인은 p의 체인보다 한 단계 더 길다.
t
→p
→Person.prototype
→Object.prototype
(종료점)
다른 프로토타입 체인은 더 이상 사용되지 않습니다.Thief
그리고.Person
시제품 체인에서 같은 부모를 공유하는 형제자매입니다.
Person
}
Thief
} →Function.prototype
→Object.prototype
(종료점)
앞에서 제시한 그래픽을 이 그래픽으로 확장할 수 있습니다(원본).Thief.prototype
생략) :
파란색 선은 프로토타입 체인을 나타내고, 다른 색 선은 다른 관계를 나타냅니다.
- 객체와 생성자 사이에
- 생성자와 객체 생성에 사용되는 프로토타입 객체 간
의 개념prototypal
상속은 많은 개발자들에게 가장 복잡한 것 중 하나입니다.문제의 근원을 파악하여 이해합시다.prototypal inheritance
낫다.먼저 a부터 시작합시다.plain
기능.
를 사용하는 경우new
의 오퍼레이터Tree function
, 라고 부릅니다.constructor
기능.
모든JavaScript
함수는prototype
. 로그인을 할 때Tree.prototype
, 당신은...
위의 내용을 보시면console.log()
출력, 에 컨스트럭터 속성을 표시할 수 있습니다.Tree.prototype
및 a__proto__
부동산도 마찬가지입니다.그__proto__
를 나타냅니다.prototype
이렇게function
기초가 되어 있고, 이건 그냥 평범한 일이기 때문에JavaScript function
없음으로inheritance
아직 셋업되지 않았습니다.Object prototype
JavaScript에 내장되어 있습니다.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
이거는 이런 게 있어요.toString, .toValue, .hasOwnProperty
기타...
__proto__
내 Mozilla는 폐지되고 다음으로 대체된다.Object.getPrototypeOf
입수 방법object's prototype
.
Object.getPrototypeOf(Tree.prototype); // Object {}
여기에 메서드를 추가해 보겠습니다.Tree
prototype
.
수정했습니다.Root
그리고 a를 추가했다.function
가지치기.
즉, 이 명령어를 작성했을 때instance
의Tree
, 라고 부를 수 있습니다.branch
방법.
추가도 가능합니다.primitives
또는objects
델에게Prototype
.
a를 추가합시다.child-tree
델에게Tree
.
여기에서는,Child
상속하다prototype
Tree에서 우리가 여기서 하고 있는 것은Object.create()
패스한 내용을 기반으로 새 개체를 만드는 방법. 여기 있습니다.Tree.prototype
이 경우 Child의 프로토타입을 새로운 오브젝트로 설정하고 있습니다.Tree
프로토타입입니다.다음으로 설정하겠습니다.Child's constructor to Child
그렇게 하지 않으면Tree()
.
Child
이제 그만의 것이 있다prototype
,그것의.__proto__
가리키다Tree
그리고.Tree's prototype
베이스 포인트Object
.
Child
|
\
\
Tree.prototype
- branch
|
|
\
\
Object.prototype
-toString
-valueOf
-etc., etc.
이 시점에서,instance
의Child
및 콜branch
이것은 원래 에서 구할 수 있습니다.Tree
아직 정의하지 않았습니다.branch
에서Child prototype
근데...Root prototype
어떤 아이가 상속받는지.
JS에서는 모든 것이 객체가 아니라 모든 것이 객체처럼 동작할 수 있습니다.
Javascript
와 같은 원초적 요소를 가지고 있다strings, number, booleans, undefined, null.
그들은 아니다object(i.e reference types)
, 하지만 확실히, 그 동작은,object
예를 들어 보겠습니다.
이 목록의 첫 번째 줄에는primitive
string 값은 이름에 할당됩니다.두 번째 행은 이름을 다음과 같이 취급합니다.object
및 콜charAt(0)
도트 표기법을 사용합니다.
이면에서는 다음과 같은 일이 발생합니다.// 이면에는JavaScript
엔진이 작동하다
그String object
1개의 스테이트먼트에 대해서만 존재합니다(프로세스라고 하는 프로세스).autoboxing
) 다시 한 번 다음 주제로 돌아가겠습니다.prototypal
inheritance
.
Javascript
를 통한 상속 지원delegation
에 기반을 둔prototypes
.- 각각
Function
가 있다prototype
property: 다른 개체를 참조합니다. properties/functions
에서 보다object
그 자체 또는 경유prototype
존재하지 않는 경우 체인
A prototype
JS에서 JS는 다음과 같은 오브젝트입니다.yields
다른 사람의 부모에게object
. [즉, 위임] Delegation
할 수 없는 일이 있으면 다른 사람에게 부탁한다는 뜻이에요.
https://jsfiddle.net/say0tzpL/1/
위의 바이올린을 찾아보면, 개는 에 액세스 할 수 있습니다.toString
방법, 그러나 이 방법에서는 사용할 수 없지만 시제품 체인을 통해 사용할 수 있습니다.Object.prototype
아래를 보시면, 저희는 이 컴퓨터에 접속하려고 합니다.call
누구나 이용할 수 있는 방법function
.
https://jsfiddle.net/rknffckc/
위의 바이올린을 찾아보면Profile
함수는 다음 항목에 액세스할 수 있습니다.call
방법, 그러나 이 방법에서는 사용할 수 없지만 시제품 체인을 통해 사용할 수 있습니다.Function.prototype
주의: prototype
는 함수 생성자의 속성이지만,__proto__
는 함수 생성자에서 생성된 객체의 속성입니다.모든 기능에는prototype
값이 비어 있는 속성object
함수의 인스턴스를 생성하면 내부 속성이 생성됩니다.[[Prototype]]
또는__proto__
이 함수의 원형을 참조한다.constructor
.
위의 도표는 조금 복잡해 보이지만, 어떻게 해야 하는지에 대한 전체 그림을 보여준다.prototype chaining
이제 천천히 설명하겠습니다.
두 가지 예가 있습니다.b1
그리고.b2
그 컨스트럭터는Bar
그리고 부모는 Foo이고 시제품 체인에서 두 가지 방법을 가지고 있다.identify
그리고.speak
경유로Bar
그리고.Foo
https://jsfiddle.net/kbp7jr7n/
위의 코드를 찾아보면Foo
방법을 가진 컨스트럭터identify()
그리고.Bar
을 가진 컨스트럭터speak
방법.2개 작성Bar
사례b1
그리고.b2
부모 타입은Foo
지금 전화하는 동안speak
의 방법Bar
speak 발신자를 특정할 수 있습니다.prototype
쇠사슬을 채우다
Bar
이제 할 수 있는 모든 방법을 가지고 있다Foo
에 정의되어 있습니다.prototype
이제 더 자세히 알아보겠습니다.Object.prototype
그리고.Function.prototype
어떤 관계인지도 알 수 있습니다.의 컨스트럭터를 검색하면Foo
,Bar
그리고.Object
이다Function constructor
.
그prototype
의Bar
이Foo
,prototype
의Foo
이Object
그리고 자세히 보면prototype
의Foo
관련되다Object.prototype
.
이 작업을 종료하기 전에 위의 모든 내용을 요약하기 위해 작은 코드로 마무리하겠습니다.사용하고 있습니다.instanceof
여기 연산자가 있는지 확인합니다.object
안에 있다prototype
쇠사슬을 채우다prototype
의 특성constructor
아래는 전체 큰 그림을 요약한 것입니다.
이 추가 정보가 있으면 좋겠는데, 파악하는데 큰 도움이 될 수 있다는 걸 알지만...간단히 말하면 물건과 연결된 물건일 뿐이에요!!!!
이 ".timeout" 속성의 정확한 목적은 무엇입니까?
표준 클래스에 대한 인터페이스가 확장 가능하게 됩니다.예를 들어,Array
또한 모든 어레이 개체에 대해 커스텀 시리얼라이저를 추가해야 합니다.서브클래스를 코드화하는 데 시간을 할애하시겠습니까, 아니면 작문이나...프로토타입 속성은 사용자가 클래스에 사용할 수 있는 멤버/메서드의 정확한 집합을 제어할 수 있도록 함으로써 이 문제를 해결합니다.
프로토타입을 여분의 비디오 포인터로 생각해 보십시오.원본 클래스에 일부 멤버가 없는 경우 런타임에 프로토타입을 검색합니다.
오브젝트 지향 JavaScript의 최종 가이드 - 질문에 대한 매우 간결하고 명료한 비디오 설명(프로토타입 상속 토픽은 5:45부터 시작됩니다만, 비디오 전체를 듣고 싶습니다).이 비디오의 작성자는 JavaScript 객체 비주얼라이저 웹사이트 http://www.objectplayground.com/도 만들었습니다.
나는 "프로토타입 체인"을 재귀적 관례로 설명하는 것이 도움이 된다는 것을 알았다.obj_n.prop_X
참조되고 있습니다.
한다면obj_n.prop_X
존재하지 않습니다. 확인하세요.obj_n+1.prop_X
어디에obj_n+1 = obj_n.[[prototype]]
이 경우,prop_X
K번째 프로토타입 개체에서 마침내 발견됨
obj_1.prop_X = obj_1.[[prototype]].[[prototype]]..(k-times)..[[prototype]].prop_X
Javascript 객체의 속성별 관계 그래프는 다음과 같습니다.
생성자가 개체를 만들 때 해당 개체는 속성 참조를 해결하기 위해 생성자의 "프로토타입" 속성을 암시적으로 참조합니다.생성자의 "protype" 속성은 프로그램 표현식 constructor.protype에서 참조할 수 있으며 개체의 프로토타입에 추가된 속성은 상속을 통해 프로토타입을 공유하는 모든 개체에서 공유됩니다.
여기에 설명이 필요한 두 개의 서로 다른 관련 주체가 있습니다.
- 그
.prototype
함수의 속성. - 그
[[Prototype]]
[1] 모든[2] 객체의 속성.
이 두 가지는 다른 것입니다.
그[[Prototype]]
속성:
이것은 모든 개체에 존재하는[2] 속성입니다.
여기에 저장되어 있는 것은 다른 오브젝트입니다.개체 자체로서 이 오브젝트에는[[Prototype]]
다른 물체를 가리키고 있습니다.다른 오브젝트에는[[Prototype]]
그 자체입니다.이 이야기는 모든 개체에 액세스할 수 있는 메서드를 제공하는 프로토타입 개체에 도달할 때까지 계속됩니다(예: ).
그[[Prototype]]
성질은 을 형성하는 것의 일부입니다.[[Prototype]]
체인이요. 이 체인이[[Prototype]]
오브젝트는 예를 들어 다음과 같은 경우에 검사되는 것입니다.[[Get]]
또는[[Set]]
조작은 오브젝트에 대해 수행됩니다.
var obj = {}
obj.a // [[Get]] consults prototype chain
obj.b = 20 // [[Set]] consults prototype chain
그.prototype
속성:
이것은 함수에서만 찾을 수 있는 속성입니다.매우 간단한 기능 사용:
function Bar(){};
그.prototype
속성에는 할당되는 개체가 있습니다.b.[[Prototype]]
할 때var b = new Bar
이것은 간단하게 조사할 수 있습니다.
// Both assign Bar.prototype to b1/b2[[Prototype]]
var b = new Bar;
// Object.getPrototypeOf grabs the objects [[Prototype]]
console.log(Object.getPrototypeOf(b) === Bar.prototype) // true
가장 중요한 것 중 하나는.prototype
s는 함수의 것입니다.이 프로토타입은 프로토타입 물체를 고정하고 있습니다.[[Prototype]]
체인은 다음을 포함합니다.그 위에 새 개체에 대해 사용 가능한 모든 메서드가 정의됩니다.
// Get properties that are defined on this object
console.log(Object.getOwnPropertyDescriptors(Object.prototype))
자, 그 이후로.prototype
오브젝트입니다.[[Prototype]]
소유물.할당하지 않을 때Function.prototype
,그.prototype
의[[Prototype]]
프로토타입 객체를 가리킵니다(Object.prototype
) 새로운 기능을 만들 때마다 자동으로 실행됩니다.
이렇게 하면 언제든지new Bar;
프로토타입 체인이 셋업되어 있습니다.모든 것이 정의되어 있습니다.Bar.prototype
정의되어 있는 모든 것Object.prototype
:
var b = new Bar;
// Get all Bar.prototype properties
console.log(b.__proto__ === Bar.prototype)
// Get all Object.prototype properties
console.log(b.__proto__.__proto__ === Object.prototype)
에 할당하는 경우Function.prototype
프로토타입 체인을 확장하여 다른 객체를 포함하도록 하는 것 뿐입니다.단일 링크 목록에 삽입하는 것과 같습니다.
이 때문에 기본적으로는[[Prototype]]
연결된 개체에 정의된 속성을 허용하는 체인Function.prototype
함수에 의해 생성된 객체에 의해 표시됩니다.
[1: 이 기능은 다른 사람에게 혼란을 주지 않습니다.많은 구현에서 이 서비스를 이용할 수 있습니다.
[2]: 를 제외한 모든 것.
시제품에 대한 저의 이해를 말씀드리겠습니다.나는 이곳의 유산을 다른 언어와 비교하지 않을 것이다.나는 사람들이 언어를 그만 비교하고 언어 자체를 이해했으면 좋겠어.프로토타입과 프로토타입 상속을 이해하는 것은 아래 그림과 같이 매우 간단합니다.
프로토타입은 모델을 기반으로 제품을 만듭니다.이해해야 할 중요한 점은 다른 개체를 프로토타입으로 사용하여 개체를 만들 때 프로토타입과 제품 간의 연결이 영원하다는 것입니다.예:
var model = {x:2};
var product = Object.create(model);
model.y = 5;
product.y
=>5
모든 오브젝트에는 [protype]라고 불리는 내부 속성이 포함되어 있습니다.이러한 속성은Object.getPrototypeOf()
기능. Object.create(model)
새 개체를 만들고 해당 개체의 [subject]속성을 개체 모델로 설정합니다.그렇기 때문에 할 때Object.getPrototypeOf(product)
오브젝트 모델이 표시됩니다.
제품의 속성은 다음과 같은 방법으로 처리됩니다.
- 속성의 값을 읽기 위해 속성에 액세스하면 해당 속성은 스코프 체인으로 검색됩니다.변수 검색은 제품에서 프로토타입까지 시작됩니다.검색에서 이러한 변수가 발견되면 검색이 바로 중지되고 값이 반환됩니다.스코프 체인에서 이러한 변수를 찾을 수 없는 경우 정의되지 않은 변수가 반환됩니다.
- 속성이 기록(변경)되면 속성은 항상 제품 개체에 기록됩니다.제품에 아직 이러한 속성이 없는 경우 암시적으로 생성되고 작성됩니다.
프로토타입 속성을 사용하여 물체를 연결하는 것을 프로토타입 유전이라고 합니다.아주 간단해, 그렇지?
JavaScript 프로토타입 기반 상속을 더 나은 이미지로 설명하려는 또 다른 시도
다음 사항을 고려하십시오.keyValueStore
오브젝트:
var keyValueStore = (function() {
var count = 0;
var kvs = function() {
count++;
this.data = {};
this.get = function(key) { return this.data[key]; };
this.set = function(key, value) { this.data[key] = value; };
this.delete = function(key) { delete this.data[key]; };
this.getLength = function() {
var l = 0;
for (p in this.data) l++;
return l;
}
};
return { // Singleton public properties
'create' : function() { return new kvs(); },
'count' : function() { return count; }
};
})();
이 오브젝트의 새 인스턴스를 작성하려면 다음 절차를 수행합니다.
kvs = keyValueStore.create();
이 개체의 각 인스턴스에는 다음과 같은 공용 속성이 있습니다.
data
get
set
delete
getLength
여기서 100개의 인스턴스를 생성한다고 가정해 보겠습니다.keyValueStore
물건.그럼에도 불구하고.get
,set
,delete
,getLength
는 이러한 100개의 인스턴스 각각에 대해 동일한 작업을 수행합니다.각 인스턴스에는 이 함수의 자체 복사본이 있습니다.
자, 상상해보세요. 만약 당신이 싱글을get
,set
,delete
그리고.getLength
각 인스턴스는 동일한 기능을 참조합니다.이것은 퍼포먼스에 도움이 되고, 필요한 메모리도 적어집니다.
거기서 프로토타입을 만들 수 있습니다.프로토타입은 상속되지만 인스턴스에 의해 복사되지 않는 속성의 "블라인도"입니다.즉, 개체의 모든 인스턴스에 대해 메모리에 한 번만 존재하며 이러한 모든 인스턴스에서 공유됩니다.
자, 이제 다음 사항을 고려하겠습니다.keyValueStore
다시 이의를 제기합니다.다음과 같이 다시 쓸 수 있습니다.
var keyValueStore = (function() {
var count = 0;
var kvs = function() {
count++;
this.data = {};
};
kvs.prototype = {
'get' : function(key) { return this.data[key]; },
'set' : function(key, value) { this.data[key] = value; },
'delete' : function(key) { delete this.data[key]; },
'getLength' : function() {
var l = 0;
for (p in this.data) l++;
return l;
}
};
return {
'create' : function() { return new kvs(); },
'count' : function() { return count; }
};
})();
이것은, 의 이전 버전과 완전히 같은 동작을 합니다.keyValueStore
모든 방법이 이제 프로토타입에 들어간다는 점을 제외하고 객체.즉, 100개의 인스턴스가 각각 고유한 복사본을 갖는 대신 이 4가지 메서드를 공유하게 됩니다.
요약:.
- 함수는 javascript의 객체이므로 속성을 가질 수 있습니다.
- (시공자) 함수는 항상 프로토타입 속성을 가집니다.
- 함수가 생성자로 사용되는 경우
new
키워드를 지정하면 오브젝트가 프로토타입을 가져옵니다.이 프로토타입에 대한 참조는 다음 웹 사이트에서 확인할 수 있습니다.__proto__
새로 생성된 객체의 속성. - 이것.
__proto__
속성은prototype
생성자 함수의 속성입니다.
예:
function Person (name) {
this.name = name;
}
let me = new Person('willem');
console.log(Person.prototype) // Person has a prototype property
console.log(Person.prototype === me.__proto__) // the __proto__ property of the instance refers to prototype property of the function.
이것이 유용한 이유:
Javascript는 객체에서 속성을 조회할 때 'prototype inheritation'이라고 하는 메커니즘이 있습니다.기본적으로 다음과 같습니다.
- 먼저 속성이 개체 자체에 있는지 확인합니다.이 경우 이 속성은 반환됩니다.
- 속성이 개체 자체에 위치하지 않으면 '프로토체인 위로 올라갑니다'.이것은 기본적으로 프로토타입의 성질에 의해 참조되는 물체를 봅니다.여기서 프로토타입에 의해 참조된 객체에 속성을 사용할 수 있는지 확인합니다.
- 만약 그 특성이 프로토 오브젝트에 없다면, 그것은 오브젝트 오브젝트까지 프로토 체인을 타고 올라갑니다.
- 개체와 프로토타입 체인의 아무 곳에서도 속성을 찾을 수 없는 경우 정의되지 않은 상태로 반환됩니다.
예를 들어 다음과 같습니다.
function Person(name) {
this.name = name;
}
let mySelf = new Person('Willem');
console.log(mySelf.__proto__ === Person.prototype);
console.log(mySelf.__proto__.__proto__ === Object.prototype);
업데이트:
그__proto__
대부분의 최신 브라우저에 구현되어 있지만 프로토타입 객체 참조를 얻는 더 나은 방법은 다음과 같습니다.
Object.getPrototypeOf()
나는 이런 종류의 것들을 이해하는 것에 있어서 항상 유추적인 것을 좋아한다.프로토타입이 훨씬 더 단순한 패러다임임에도 불구하고, 내 생각에 '프로토타입 상속'은 클래스 베이스 상속과 비교했을 때 상당히 혼란스럽다.사실 프로토타입에는 상속이 없기 때문에 이름 자체가 오해를 불러일으키는 것은 일종의 '위임'에 가깝습니다.
상상해 보세요…
넌 고등학생이고 오늘까지 수업 중이고 퀴즈도 내야 하는데 답안을 작성할 펜이 없잖아.도!
펜이 있을지도 모르는 친구 피니우스 옆에 앉아 있잖아여러분이 물으면, 그는 책상을 둘러보는데 실패하지만, "저는 펜이 없어요"라고 말하는 대신, 그는 좋은 친구이고, 그가 펜을 가지고 있는지 다른 친구 더프에게 확인합니다.Derp는 여분의 펜을 가지고 있고 그것을 Finnius에게 돌려주고, Finnius는 퀴즈를 완성하기 위해 그것을 당신에게 건네줍니다.더프는 펜을 피니우스에게 맡겼고, 피니우스는 펜을 사용할 수 있도록 당신에게 위임했습니다.
여기서 중요한 것은 Derp가 당신에게 펜을 주지 않는 것입니다. 왜냐하면 당신은 Derp와 직접적인 관계가 없기 때문입니다.
다음은 프로토타입의 작동 방식을 단순화한 예입니다. 여기서 데이터 트리를 검색하여 원하는 항목을 찾습니다.
__discript__, 프로토타입 및 생성자 관계를 보여주는 또 다른 체계:
단지 당신은 이미 다른 사람들과의 관계를 가지고 있을 뿐입니다.Object.new
생성자 구문을 사용할 때 아직 개체가 없습니다.
오브젝트의 프로토타입 사이에는 차이가 있다는 것을 이해하는 것이 중요합니다(다음에서 입수할 수 있습니다).
Object.getPrototypeOf(obj)
또는 권장되지 않는 경유로__proto__
프로퍼티)prototype
생성자 함수의 속성입니다.전자는 각 인스턴스의 속성이고 후자는 생성자의 속성입니다.그것은,Object.getPrototypeOf(new Foobar())
와 같은 오브젝트를 참조하다Foobar.prototype
.
참고 자료: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes
프로토타입은 기존 개체를 복제하여 새 개체를 생성합니다.프로토타입에 대해 생각해보면복제나 복사를 만드는 것이 아니라 생각할 수 있습니다
프로토타입 및 프로토타입 기반 상속의 개념을 기본적으로 이해하고 싶다면 공식 MDN 문서를 참조하십시오. 이 문서는 매우 잘 설명되어 있습니다.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
상속과 관련하여 JavaScript에는 객체라는 하나의 구성체만 있습니다.각 개체에는 프로토타입이라고 불리는 다른 개체로의 링크가 있는 개인 속성이 있습니다.이 프로토타입 객체는 자체 프로토타입을 가지고 있으며, Null을 프로토타입을 사용하여 객체에 도달할 때까지 계속됩니다.정의에 따르면 null에는 프로토타입이 없으며 이 프로토타입 체인의 최종 링크 역할을 합니다.
또한 간단한 예를 사용하여 설명하는 다른 유용한 리소스도 있습니다. https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes
언급URL : https://stackoverflow.com/questions/572897/how-does-javascript-prototype-work
'programing' 카테고리의 다른 글
go lang에서 db에서 데이터를 가져오는 방법 (0) | 2022.10.30 |
---|---|
표의 열 순서를 걱정할 이유가 있나요? (0) | 2022.10.30 |
JQuery UI Datepicker 필드의 수동 입력을 비활성화하려면 어떻게 해야 합니까? (0) | 2022.10.30 |
MySQL 8에서 Maria로 대용량 데이터베이스 마이그레이션DB (0) | 2022.10.20 |
등록 후 사용자 자동 인증 (0) | 2022.10.20 |