programing

JavaScript에서 프로토타입 상속 이해

javajsp 2023. 10. 26. 20:45

JavaScript에서 프로토타입 상속 이해

자바스크립트 OOP는 처음입니다.아래의 코드 블록들의 차이점을 설명해주시겠습니까?테스트를 해봤는데 두 블록 모두 작동합니다.가장 좋은 방법은 무엇이고 그 이유는 무엇입니까?

첫번째 블럭:

function Car(name){
    this.Name = name;
}

Car.prototype.Drive = function(){
    console.log("My name is " + this.Name + " and I'm driving.");
}

SuperCar.prototype = new Car();
SuperCar.prototype.constructor = SuperCar;

function SuperCar(name){
    Car.call(this, name);
}

SuperCar.prototype.Fly = function(){
    console.log("My name is " + this.Name + " and I'm flying!");
}

var myCar = new Car("Car");
myCar.Drive();

var mySuperCar = new SuperCar("SuperCar");
mySuperCar.Drive();
mySuperCar.Fly();

두번째 블록:

function Car(name){
    this.Name = name;
    this.Drive = function(){ 
        console.log("My name is " + this.Name + " and I'm driving.");
    }
}

SuperCar.prototype = new Car();

function SuperCar(name){
    Car.call(this, name);
    this.Fly = function(){
        console.log("My name is " + this.Name + " and I'm flying!");
    }
}

var myCar = new Car("Car");
myCar.Drive();

var mySuperCar = new SuperCar("SuperCar");
mySuperCar.Drive();
mySuperCar.Fly();

저자가 추가한 이유는 무엇인가요?Drive그리고.Fly사용 방법prototype, 그리고 그들을 a로 선언하지 않았습니다.this.Drive메소드 인 더 인더Car격에 따라this.FlySuperCar업?

왜 그럴까요?SuperCar.prototype.constructor되돌려야 할 필요가 있습니다SuperCar? ?constructor속성은 다음 시간에 무시됩니다.prototype준비되었습니까?저는 이 대사에 대해 코멘트를 해보았지만 아무것도 변한 것이 없습니다.

호출 이유Car.call(this, name);SuperCar시공자?의 속성 및 방법이 없을 것입니다.Car내가 할 때는 '세습'을 당합니다.

var myCar = new Car("Car");

Norbert Hartl의 답변에 더해 SuperCar.prototype.constructor는 필요하지 않지만 어떤 사람들은 그것을 객체(이 경우 SuperCar 객체)의 구성 기능을 얻는 편리한 방법으로 사용합니다.

첫 번째 예에서 본 것처럼, Car.call(이것, name)은 슈퍼카 컨스트럭터 기능에 포함되어 있습니다.

var mySuperCar = new SuperCar("SuperCar");

자바스크립트가 하는 일은 다음과 같습니다.

  1. 새로워진 빈 개체가 인스턴스화됩니다.
  2. 새 물체의 내부 원형은 Car로 설정되어 있습니다.
  3. 슈퍼카 컨스트럭터 기능이 실행됩니다.
  4. 완성된 오브젝트는 반환되어 내 슈퍼카에 설정됩니다.

자바스크립트가 어떻게 Car를 불러주지 않았는지 주목해보세요.프로토타입은 그대로이며, SuperCar를 위해 직접 설정하지 않은 모든 속성이나 방법은 Car에서 조회됩니다.SuperCar에는 Drive(드라이브) 방식이 없지만, Car(드라이브) 방식을 공유할 수 있으므로 모든 SuperCar는 동일한 Drive(드라이브) 방식을 사용합니다.슈퍼카마다 이름이 있는 것처럼 공유를 원하지 않을 때도 있습니다.그렇다면 사람들은 어떻게 각각의 슈퍼카의 이름을 자신만의 것으로 설정할 수 있을까요?이걸 설정할 수 있습니다.슈퍼카 컨스트럭터 기능 내부의 이름:

function SuperCar(name){
    this.Name = name;
}

이 방법은 효과가 있습니다만, 잠시만요.우리가 자동차 제작사에서 똑같이 하지 않았습니까?반복하고 싶지 않습니다.이름은 이미 Car가 정했으니 그냥 부르자.

function SuperCar(name){
    this = Car(name);
}

이런, 당신은 특별한 것을 바꾸고 싶지 않을 겁니다.this객체 참조 4단계하십니까?단계를 기억하십니까?자바스크립트가 준 그 물체를 붙잡아라, 왜냐하면 그것이 당신의 SuperCar 물체와 자동차 사이의 소중한 내부 프로토타입 링크를 유지할 수 있는 유일한 방법이기 때문이다.그렇다면 새로운 슈퍼카 객체인 자바스크립트가 우리를 준비하기 위해 그렇게 많은 특별한 노력을 들여서 포기하지 않고 이름을 설정할 수 있는 방법은 무엇일까요.

두 가지.하나: 다음의 의미this유연합니다. 자동차는 기능입니다.둘: 자동차는 기능입니다.카라고 부르는 것은 자연 그대로의 신선한 인스턴스화된 물체가 아니라 슈퍼카 물체를 사용하는 것이 가능합니다.이를 통해 최종 솔루션이 제공되며, 이 솔루션은 질문의 첫 번째 예 중 일부입니다.

function SuperCar(name){
    Car.call(this, name);
}

함수로서, Car는 그 함수의 호출 방식으로 호출될 수 있고, 이것은 의미를 바꿉니다.this자동차 안에서 슈퍼카를 만들 겁니다프레스토! 속성이 .이제 각 슈퍼카는 고유의 Name 속성을 갖게 됩니다.

마지막으로.Car.call(this, name)SuperCar Constructor는 새로운 SuperCar 객체마다 고유한 Name 속성을 부여하지만, 이미 존재하는 코드를 복제하지는 않습니다.

프로토타입은 한 번 이해하면 무섭지 않지만, 기존 클래스/상속 OOP 모델과는 전혀 다릅니다.자바스크립트로 프로토타입 개념에 대한 기사를 작성했습니다.자바스크립트를 사용하는 게임 엔진을 위해 작성된 것이지만 파이어폭스에서 사용하는 자바스크립트 엔진과 동일하므로 모두 관련이 있을 것입니다.

두 블록은 첫 번째 예에서 다른 점이 있습니다.Drive()두 번째 접근 시 한 번만 존재할 것입니다.Drive()각 인스턴스마다 존재할 것입니다(매번 존재)new Car()edrive()다시 생성됩니다).또는 다른 말로는 첫 번째는 프로토타입을 사용하여 함수를 저장하고 두 번째는 생성자를 저장합니다.함수에 대한 조회는 생성자이고 프로토타입입니다.그래서 당신이 알아본 것은Drive()구축자에 있든 프로토타입에 있든 상관없이 이를 찾습니다.프로토타입을 사용하는 것이 더 효율적입니다. 보통 타입당 한 번만 기능이 필요하기 때문입니다.

newcall in javascript는 프로토타입에 생성자를 자동으로 설정합니다.프로토타입을 덮어쓰는 경우 생성자를 수동으로 설정해야 합니다.

javascript의 상속은 다음과 같습니다.super 수 는 슈퍼컨스트럭터의 따라서 하위 클래스가 있다면 슈퍼 컨스트럭터를 부를 수 있는 유일한 기회는 이름뿐입니다.

노버트, 당신의 첫번째 예는 Douglas Crockford가 말하는 유사 고전 유산입니다.이와 관련하여 주의해야 할 사항:

  1. 자동차 제작자에게 두 번 전화를 걸게 됩니다. 한 번은 SuperCar.prototype = newCar() 라인에서, 다른 한 번은 "constructor stealing" 라인에서 전화를 걸게 됩니다.프로토타입을 상속할 도우미 메소드를 생성할 수 있으며, 차량 제작자는 설정 효율을 높이기 위해 한 번만 실행하면 됩니다.
  2. SuperCar.prototype.constructor = SuperCar 라인에서는 의 인스턴스(instance)를 사용하여 Constructor를 식별할 수 있습니다.어떤 사람들은 이것을 원하기도 하고 다른 사람들은 예를 사용하지 않기도 합니다.
  3. 참조 변수는 다음과 같습니다. 슈퍼(예: Car)에서 정의될 때 vararar = ['one','two'] 가 모든 인스턴스에 공유됩니다.이는 모든 인스턴스에 대해 inst1.arr.push['3'], inst2.arr.push['4'] 등이 표시됨을 의미합니다.근본적으로 당신이 원하지 않는 정적인 행동입니다.
  4. 두 번째 블럭은 생성자에서 플라이 메소드를 정의합니다.이는 호출될 때마다 "메소드 개체"가 생성됨을 의미합니다.방법은 프로토타입을 사용하는 것이 좋습니다!하지만 원한다면 컨스트럭터에 보관할 수도 있습니다. 실제로 프로토타입 리터럴을 한 번(pseudo)만 초기화하면 됩니다. 만약(SuperCar.prototype.myMethod!= 'function')..프로토타입 리터럴을 정의합니다.
  5. '왜 Car.call(이것, 이름)을 부르세요.': 제가 틀릴 수도 있지만, 이는 보통 제가 위에서 설명한 프로토타입 체인의 '정적' 동작 문제를 해결하기 위해 각 인스턴스가 고유한 상태를 유지할 수 있도록 하기 위한 것입니다.

마지막으로, 여기서 작동하는 TDD 자바스크립트 상속 코드의 몇 가지 예를 말씀드리고 싶습니다: TDD 자바스크립트 상속 코드와 에세이. 개선하여 오픈소스로 유지하고자 하므로 귀하의 피드백을 받고 싶습니다.목표는 고전적인 프로그래머들이 자바스크립트로 빠르게 속도를 낼 수 있도록 돕는 것이며, 또한 크로포드와 자카스 책 모두를 연구를 보완하는 것입니다.

100% 확신할 수는 없지만, 두 번째 예는 단순히 슈퍼카 클래스의 내용을 슈퍼카 객체에 복제하는 반면, 첫 번째 예는 슈퍼카 프로토타입을 자동차 클래스에 연결하여 자동차 클래스의 런타임 변화가 슈퍼카 클래스에도 영향을 미친다는 점이 차이점이라고 생각합니다.

function abc() {
}

함수 abc에 대해 생성된 프로토타입 방법 및 속성

abc.prototype.testProperty = 'Hi, I am prototype property';
abc.prototype.testMethod = function() { 
   alert('Hi i am prototype method')
}

함수 abc에 대한 새 인스턴스를 만드는 중

var objx = new abc();

console.log(objx.testProperty); // will display Hi, I am prototype property
objx.testMethod();// alert Hi i am prototype method

var objy = new abc();

console.log(objy.testProperty); //will display Hi, I am prototype property
objy.testProperty = Hi, I am over-ridden prototype property

console.log(objy.testProperty); //will display Hi, I am over-ridden prototype property

http://astutejs.blogspot.in/2015/10/javascript-prototype-is-easy.html

여기에 몇 가지 질문이 있습니다.

아래의 코드 블록들 간의 차이점을 설명해주시겠습니까?테스트를 해봤는데 두 블록 모두 작동합니다.

첫번째는 오직 하나만 만듭니다.Drive함수, 두번째는 그들 중 두개를 생성합니다: 하나는 on입니다.myCar그리고 또 하나는mySuperCar.

첫번째 또는 두번째 블록이 실행되었을 때 다른 결과를 제공하는 코드는 다음과 같습니다.

myCar.Fly === mySuperCar.Fly // true only in the first case
Object.keys(myCar).includes("Fly") // true only in the second case
Object.keys(Car.prototype).length === 0 // true only in the second case

가장 좋은 방법은 무엇이고 그 이유는 무엇입니까?
저자가 추가한 이유는 무엇인가요?Drive그리고.Fly사용 방법prototype, 하지만 그들은 그들을 "로 선언하지는 않습니다.this.Drive메소드 인사이드Car계급과this.Fly인에SuperCar업?

프로토타입에 방법을 정의하는 것이 좋습니다. 다음과 같은 이유가 있습니다.

  • 각 방법은 한 번만 정의됩니다.
  • 각 메서드는 생성자를 실행하지 않고 생성된 인스턴스에서도 사용할 수 있습니다(호출할 때 이 경우).Object.create(Car.prototype));
  • 인스턴스의 프로토타입 체인에서 특정 메서드가 정의된 수준을 검사할 수 있습니다.

왜 그럴까요?SuperCar.prototype.constructor되돌려야 할 필요가 있습니다SuperCar? 이스constructor속성은 다음 시간에 무시됩니다.prototype준비되었습니까?저는 이 대사에 대해 코멘트를 해보았지만 아무것도 변한 것이 없습니다.

constructor속성은 다음과 같이 재정의되지 않습니다.prototype설정되어 있습니다.하지만 건설자는new Car()이다.Car, 설정하면new Car().SuperCar.prototype, 그 다음에는SuperCar.prototype.constructor이다.Car.

재할당하지 않는 한prototype, 다음과 같은 불변성이 있습니다.Constructor.prototype.constructor === Constructor. 예를 들어, 이것은 다음의 경우에 해당됩니다.Car:Car.prototype.constructor === Car, 하지만 에 대해서도 마찬가지입니다.Array,Object,String .

하지만 다른 개체를 다른 개체로 재할당하면prototype, 그 불변성은 깨졌습니다.일반적으로 문제는 아니지만, "새로운 인스턴스를 생성할 때 이 프로토타입 개체를 사용하는 생성자는 무엇입니까?"라는 질문에 답하기 때문에 복원하는 것이 좋습니다.일부 코드는 이러한 검사를 수행할 수 있으며 이에 의존합니다.이러한 경우 "프로토타입 컨스트럭터를 설정해야 하는 이유"를 참조하십시오.

호출 이유Car.call(this, name);인에SuperCar시공자?내가 할 때 Car의 속성과 방법은 '상속'되지 않을 것입니다.

var myCar = new Car("Car");

하지 않으면Car.call(this, name);그럼 당신의SuperCarinstance에는 이름 속성이 없습니다.물론 당신은 그냥 하기로 결정할 수 있습니다.this.name = name;대신에, 그것은 단지 그 안에 있는 코드를 복사합니다.Car컨스트럭터, 하지만 좀 더 복잡한 상황에서는 그런 코드 복제를 하는 것은 나쁜 관행이 될 것입니다.

전화하는 것은 도움이 되지 않을 것입니다.new Car(name)내부에SuperCar컨스트럭터, 그것이 다른 객체를 만들 것이기 때문에, 당신이 정말로 확장할 필요가 있는 동안.this물건.사용하지 않음으로써new 사용)call대신에) 당신이 사실은.Car함수는 생성자로 실행되지 않고(즉, 새 개체를 만들지 않는) 대신 전달하는 개체를 사용합니다.

시대가 변했다

자바스크립트의 최신 버전에서는 사용할 수 있습니다.super(name)대신에Car.call(this, name):

function SuperCar(name) {
    super(name);
}

오늘, 당신은 또한 사용하게 될 것입니다.class구문을 사용하고 질문의 첫 번째 코드 블록을 다음과 같이 작성합니다.

class Car {
    constructor(name) {
        this.name = name;
    }
    drive() {
        console.log(`My name is ${this.name} and I'm driving.`);
    }
}

class SuperCar extends Car {
    constructor(name) {
        super(name);
    }
    fly() {
        console.log(`My name is ${this.name} and I'm flying!`);
    }
}

const myCar = new Car("Car");
myCar.drive();

const mySuperCar = new SuperCar("SuperCar");
mySuperCar.drive();
mySuperCar.fly();

어떻게 당신이 그 일에 대해 언급할 필요가 없는지 주목하세요.prototype목적을 달성하기 위한 재산. 그.class ... extends구문은 또한 설정을 합니다.prototype.constructor당신의 질문의 첫번째 블록이 한 것과 같은 재산.

언급URL : https://stackoverflow.com/questions/892595/understanding-prototypal-inheritance-in-javascript