JavaScript의 상속 유형 상속의 좋은 예
저는 10 년 넘게 OOP 언어로 해 왔지만 지금은 JavaScript를 배우고 처음부터 프로그래밍 기반 상속을 접한 것입니다. 저는 좋은 코드를 공부하여 가장 빨리 배우는 경향이 있습니다. 유형 유형 상속을 사용하는 JavaScript 애플리케이션 (또는 라이브러리)의 잘 보관 예는 무엇입니까? 그리고 어디에서 어디서부터 읽기를 시작해야합니까?
Douglas Crockford에는 JavaScript Prototypal Inheritance 에 대한 멋진 페이지가 있습니다 .
5 년 전에 저는 JavaScript로 Classical Inheritance 를 작성 합니다. JavaScript는 클래스가없는 표현력이있는 언어이며 클래식 시스템을 시뮬레이션한다는 표현력을 가지고 있습니다. 내 프로그래밍 스타일은 좋은 프로그래머가해야하는 것처럼 그 이후로 발전했습니다. 나는 고전적 모델의 한계에서 벗어나 자신을 해방 정당습니다.
Dean Edward의 Base.js , Mootools의 클래스 또는 John Resig의 단순 상속 작업은 JavaScript에서 고전적인 상속 을 수행하는 방법 입니다.
Douglas Crockford의 영화는 이유에 대한 좋은 설명을 제공하며 방법을 다룹니다. 그러나 몇 줄의 JavaScript에 있는지 여부 :
// Declaring our Animal object
var Animal = function () {
this.name = 'unknown';
this.getName = function () {
return this.name;
}
return this;
};
// Declaring our Dog object
var Dog = function () {
// A private variable here
var private = 42;
// overriding the name
this.name = "Bello";
// Implementing ".bark()"
this.bark = function () {
return 'MEOW';
}
return this;
};
// Dog extends animal
Dog.prototype = new Animal();
// -- Done declaring --
// Creating an instance of Dog.
var dog = new Dog();
// Proving our case
console.log(
"Is dog an instance of Dog? ", dog instanceof Dog, "\n",
"Is dog an instance of Animal? ", dog instanceof Animal, "\n",
dog.bark() +"\n", // Should be: "MEOW"
dog.getName() +"\n", // Should be: "Bello"
dog.private +"\n" // Should be: 'undefined'
);
그러나이 방법의 발생은 개체를 만들 때마다 개체를 다시 생성 것입니다. 또 다른 접근 방식은 다음과 같이 준비된 스택에서 선언하는 것입니다.
// Defining test one, prototypal
var testOne = function () {};
testOne.prototype = (function () {
var me = {}, privateVariable = 42;
me.someMethod = function () {
return privateVariable;
};
me.publicVariable = "foo bar";
me.anotherMethod = function () {
return this.publicVariable;
};
return me;
}());
// Defining test two, function
var testTwo = function() {
var me = {}, privateVariable = 42;
me.someMethod = function () {
return privateVariable;
};
me.publicVariable = "foo bar";
me.anotherMethod = function () {
return this.publicVariable;
};
return me;
};
// Proving that both techniques are functionally identical
var resultTestOne = new testOne(),
resultTestTwo = new testTwo();
console.log(
resultTestOne.someMethod(), // Should print 42
resultTestOne.publicVariable // Should print "foo bar"
);
console.log(
resultTestTwo.someMethod(), // Should print 42
resultTestTwo.publicVariable // Should print "foo bar"
);
// Performance benchmark start
var stop, start, loopCount = 1000000;
// Running testOne
start = (new Date()).getTime();
for (var i = loopCount; i>0; i--) {
new testOne();
}
stop = (new Date()).getTime();
console.log('Test one took: '+ Math.round(((stop/1000) - (start/1000))*1000) +' milliseconds');
// Running testTwo
start = (new Date()).getTime();
for (var i = loopCount; i>0; i--) {
new testTwo();
}
stop = (new Date()).getTime();
console.log('Test two took: '+ Math.round(((stop/1000) - (start/1000))*1000) +' milliseconds');
자기 성찰과 관련하여 약간의 단점이 있습니다. testOne을 덤핑하면 정보가 덜 유용합니다. 또한 "testOne"의 개인 속성 "privateVariable"은 모든 경우에 공유되며 shesek의 답변에서 유용하게 참조됩니다.
function Shape(x, y) {
this.x = x;
this.y = y;
}
// 1. Explicitly call base (Shape) constructor from subclass (Circle) constructor passing this as the explicit receiver
function Circle(x, y, r) {
Shape.call(this, x, y);
this.r = r;
}
// 2. Use Object.create to construct the subclass prototype object to avoid calling the base constructor
Circle.prototype = Object.create(Shape.prototype);
나는 YUI 와 Dean Edward의 Base
도서관을 상상 볼 것입니다 : http://dean.edwards.name/weblog/2006/03/base/
YUI의 경우 lang 모듈 , esp를 빠르게 살펴볼 수 있습니다 . YAHOO.lang.extend의 방법. 그런 다음 일부 위젯 또는 유틸리티의 소스를 찾아보고 해당 방법을 사용하는 방법을 볼 수 있습니다.
Microsoft의 ASP.NET Ajax 라이브러리, http://www.asp.net/ajax/도 있습니다.
객체 지향 기술을 사용 하여 고급 웹 응용 프로그램 만들기를 포함 하여 좋은 MSDN 가이드도 많이 있습니다.
다음은 Mixu의 Node 책 ( http://book.mixu.net/node/ch6.html ) 에서 가장 명확한 예입니다 .
상속보다 구성을 선호합니다.
구성-개체의 기능은 다른 개체의 인스턴스를 포함하여 서로 다른 클래스의 집합체로 구성됩니다. 상속-객체의 기능은 자체 기능과 상위 클래스의 기능으로 구성됩니다. 상속이 필요한 일반 오래된 JS를 사용하십시오.
상속을 구현해야한다면, 또 다른 비표준 구현을 사용하지 않습니다. 다음은 순수 ES3에서 합산 팩스를 구현하는 방법입니다 (프로토 타입에서 속성을 정의하지 않는 규칙을 따르는 한).
function Animal(name) { this.name = name; }; Animal.prototype.move = function(meters) { console.log(this.name+" moved "+meters+"m."); }; function Snake() { Animal.apply(this, Array.prototype.slice.call(arguments)); }; Snake.prototype = new Animal(); Snake.prototype.move = function() { console.log("Slithering..."); Animal.prototype.move.call(this, 5); }; var sam = new Snake("Sammy the Python"); sam.move();
이것은 고전적인 상속과는입니다. 그러나 표준 생성에서는 이해하기 쉬운 자바 선언이며 사람들이 주로 찾는 기능을 가지고 있습니다 : 체인 가능한 수퍼 자와 클래스의 메소드를 호출하는 능력.
ES6 class
및extends
ES6 class
및 extends
이전에 가능한 조합 식 체인 단지 구문, 그래서 틀림없이 가장 표준적인 설정입니다.
먼저 https://stackoverflow.com/a/23877420/895245.
에서 프로토-type 체인 및 속성 조회에 대해 자세히 알아보십시오 .
이제 무슨 일이 일어나는지 분해 해 봅시다.
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.
(new C(1)).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:
// https://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
사전 정의 된 모든 개체가없는 단순화 된 다이어그램 :
__proto__
(C)<---------------(D) (d)
| | | |
| | | |
| |prototype |prototype |__proto__
| | | |
| | | |
| | | +---------+
| | | |
| | | |
| | v v
|__proto__ (D.prototype)
| | |
| | |
| | |__proto__
| | |
| | |
| | +--------------+
| | |
| | |
| v v
| (C.prototype)--->(inc)
|
v
Function.prototype
PrototypeJS의 Class.create :
83 행 @ http://prototypejs.org/assets/2009/8/31/prototype.js를 보는 것이 좋습니다 .
내가 본 최고의 예는 Douglas Crockford의 JavaScript : The Good Parts에 있습니다. 언어에 대한 균형 잡힌 견해를 제공하기 위해 구매할 가치가 있습니다.
Douglas Crockford 는 JSON 형식을 담당하며 Yahoo에서 JavaScript 전문가가 일하고 있습니다.
ECMAScript 버전 별 구현 이있는 스 니펫 JavaScript 유형 기반 상속 이 있습니다. 현재 실행에 따라 ES6, ES5 및 ES3 구현 중 사용할 항목을 자동으로 선택합니다.
Javascript에서 Prototype 기반 상속의 예를 추가합니다.
// Animal Class
function Animal (name, energy) {
this.name = name;
this.energy = energy;
}
Animal.prototype.eat = function (amount) {
console.log(this.name, "eating. Energy level: ", this.energy);
this.energy += amount;
console.log(this.name, "completed eating. Energy level: ", this.energy);
}
Animal.prototype.sleep = function (length) {
console.log(this.name, "sleeping. Energy level: ", this.energy);
this.energy -= 1;
console.log(this.name, "completed sleeping. Energy level: ", this.energy);
}
Animal.prototype.play = function (length) {
console.log(this.name, " playing. Energy level: ", this.energy);
this.energy -= length;
console.log(this.name, "completed playing. Energy level: ", this.energy);
}
// Dog Class
function Dog (name, energy, breed) {
Animal.call(this, name, energy);
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function () {
console.log(this.name, "barking. Energy level: ", this.energy);
this.energy -= 1;
console.log(this.name, "done barking. Energy level: ", this.energy);
}
Dog.prototype.showBreed = function () {
console.log(this.name,"'s breed is ", this.breed);
}
// Cat Class
function Cat (name, energy, male) {
Animal.call(this, name, energy);
this.male = male;
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.meow = function () {
console.log(this.name, "meowing. Energy level: ", this.energy);
this.energy -= 1;
console.log(this.name, "done meowing. Energy level: ", this.energy);
}
Cat.prototype.showGender = function () {
if (this.male) {
console.log(this.name, "is male.");
} else {
console.log(this.name, "is female.");
}
}
// Instances
const charlie = new Dog("Charlie", 10, "Labrador");
charlie.bark();
charlie.showBreed();
const penny = new Cat("Penny", 8, false);
penny.meow();
penny.showGender();
ES6는 생성자와 슈퍼 키워드를 사용하는 것보다 훨씬 더 쉬운 상속 구현을 사용합니다.
참고 URL : https://stackoverflow.com/questions/2064731/good-example-of-javascripts-prototype-based-inheritance
'IT' 카테고리의 다른 글
지도에 삽입하는 데 선호되는 / 관용적 인 방법은 무엇입니까? (0) | 2020.09.09 |
---|---|
내 웹 사이트의 로고를 브라우저 탭의 아이콘 이미지로 설정해야 할 필요가 있습니까? (0) | 2020.09.09 |
자바 펼치기 : 그것도 비어 있는지 확인하는 방법? (0) | 2020.09.09 |
node.js와 meteor.js의 차이점은 무엇입니까? (0) | 2020.09.09 |
JSON을 서버에 보내고 JQuery없이 JSON을 반환합니다. (0) | 2020.09.09 |