>  기사  >  웹 프론트엔드  >  js의 상속 방법은 무엇입니까?

js의 상속 방법은 무엇입니까?

PHP中文网
PHP中文网원래의
2017-06-21 09:57:371107검색

1 ES6의 상속

ES6에서는 클래스 키워드를 사용하여 클래스를 정의하고, 확장 키워드를 사용하여 클래스를 상속합니다. 상위 클래스의 "this" 객체를 얻으려면 하위 클래스의 생성자 생성자에서 super 메서드를 호출해야 합니다. super를 호출할 때 부모 생성자에 매개 변수를 전달할 수 있습니다. 하위 클래스는 슈퍼 개체를 통해 상위 클래스의 속성과 메서드를 직접 사용하거나 동일한 이름을 가진 속성이나 메서드를 통해 상위 클래스의 정의를 재정의할 수 있습니다.

class Father {
  constructor () {
    this.surname = '王'
    this.money = Infinity
  }
  sayName () {
    console.log(`My surname is ${this.surname}.`)
  }
}

class Son extends Father {
  constructor (firstname) {
    super()
    this.firstname = firstname
  }
  sayName () {
    console.log(`My name is ${super.surname}${this.firstname}.`)
  }
  sayMoney () {
    console.log(`I have ${this.money} money.`)
  }
}

let Sephirex = new Son('撕葱')
Sephirex.sayName()
Sephirex.sayMoney()

ES6의 클래스와 상속은 기본적으로 프로토타입을 사용하여 구현된 구문 설탕입니다. 클래스에 정의된 메서드는 프로토타입에서 속성을 정의하는 것과 동일합니다. 슈퍼 메서드는 메서드를 정의하는 것과 같습니다. 하위 클래스에서 상위 클래스의 생성자를 호출합니다. ES5의 상속 구현에 대해 계속 논의하겠습니다.

2 프로토타입 체인 상속

프로토타입 체인 상속의 기본 패턴은 하위 유형의 프로토타입 객체가 상위 유형의 인스턴스를 가리키도록 한 다음 해당 프로토타입에 대한 메서드를 확장하는 것입니다.

function Person (name) {
  this.name = name
  this.likes = ['apple', 'orange']
}
Person.prototype.sayName = function () {
  console.log(this.name)
}

function Worker () {
  this.job = 'worker'
}
Worker.prototype = new Person()
Worker.prototype.sayJob = function () {
  console.log(this.job)
}

let Tom = new Worker()
let Jerry = new Worker()
Tom.likes.push('grape')
console.log(Jerry.likes) // [ 'apple', 'orange', 'purple' ]

원리: 이전 기사에서 __proto__와 프로토타입에 대해 논의했습니다. 서브클래스의 인스턴스에는 생성자의 프로토타입 객체를 가리키는 __proto__ 포인터가 있습니다. 하위 클래스 생성자의 프로토타입은 상위 클래스의 인스턴스를 가리키고, 상위 클래스 인스턴스의 __proto__는 상위 클래스 생성자의 프로토타입을 가리킨다... 이런 식으로 프로토타입 체인이 형성됩니다.
부모 클래스의 참조 유형 속성이 생성자에 정의되어 있더라도 여전히 자식 클래스 인스턴스에서 공유된다는 점에 유의해야 합니다. 왜냐하면 서브클래스 생성자의 프로토타입이 실제로는 부모 클래스의 인스턴스이기 때문에 부모 클래스의 인스턴스 속성은 자연스럽게 서브클래스의 프로토타입 속성이 되고, 참조형 값의 프로토타입 속성은 인스턴스 간에 공유되기 때문입니다.
프로토타입 체인의 또 다른 문제는 모든 객체 인스턴스에 영향을 주지 않고 상위 클래스의 생성자에 매개변수를 전달할 수 있는 방법이 없다는 것입니다. 위의 예와 같이 Worker.prototype = new Person()을 사용하여 하위 클래스 프로토타입이 상위 클래스 인스턴스를 가리키도록 할 때 초기화 매개변수가 전달되면 모든 하위 클래스의 인스턴스 이름 속성이 전달된 매개변수가 됩니다. 여기에 매개변수가 전달되지 않으면 나중에 매개변수를 상위 클래스 생성자에 전달할 방법이 없습니다. 따라서 프로토타입 체인 상속 패턴은 단독으로 사용되는 경우가 거의 없습니다.

3 생성자 차용

생성자 차용을 사용하면 참조 유형 속성이 공유되는 문제를 해결할 수 있습니다. 소위 생성자를 "빌리는" 것은 하위 클래스의 생성자에서 상위 클래스의 생성자를 호출하는 것입니다. 함수에서 이 점은 함수가 정의된 위치와 아무 관련이 없다는 점을 잊지 마십시오. 그것이 호출되는 곳에서만. ES6 하위 클래스 생성자에서 슈퍼 메서드를 호출하는 것과 유사하게 call 또는 Apply를 사용하여 하위 클래스 인스턴스에서 상위 클래스의 생성자를 호출하여 상위 클래스의 속성과 메서드를 얻을 수 있습니다.

function Person (name) {
  this.name = name
  this.likes = ['apple', 'orange']
}

function Worker (name) {
  Person.call(this, name)
  this.job = 'worker'
}

let Tom = new Worker('Tom')
Tom.likes.push("grape")

let Jerry = new Worker('Jerry')

console.log(Tom.likes) // [ 'apple', 'orange', 'grape' ]
console.log(Jerry.likes) // [ 'apple', 'orange' ]

단순히 생성자를 사용할 때의 문제점은 함수를 재사용할 수 없고 하위 클래스가 상위 클래스 프로토타입의 속성과 메서드를 얻을 수 없다는 것입니다.

4 조합 상속

조합 상속은 생성자를 빌려 인스턴스 속성을 정의하고 프로토타입 체인 공유 방법을 사용합니다. 결합 상속은 프로토타입 체인 모드와 빌린 생성자를 결합하여 두 가지의 장점을 활용하고 각각의 단점을 보완합니다. js에서 가장 일반적으로 사용되는 상속 모드입니다.

function Person (name) {
  this.name = name
  this.likes = ['apple', 'orange']
}
Person.prototype.sayName = function () {
  console.log(this.name)
}

function Worker (name, job) {
  Person.call(this, name) // 第二次调用 Person()
  this.job = job
}
Worker.prototype = new Person() // 第一次调用 Person()
Worker.prototype.constructor = Worker
Worker.prototype.sayJob = function () {
  console.log(this.job)
}

let Tom = new Worker('Tom', 'electrician')
Tom.likes.push('grape')
console.log(Tom.likes) // [ 'apple', 'orange', 'grape' ]
Tom.sayName() // Tom
Tom.sayJob() // electrician

let Jerry = new Worker('Jerry', 'woodworker')
console.log(Jerry.likes) // [ 'apple', 'orange' ]
Jerry.sayName() // Jerry
Jerry.sayJob() // woodworker

결합 상속에는 단점이 있습니다. 즉, 상속 프로세스에서 상위 클래스 생성자를 두 번 호출합니다. Person 생성자가 처음 호출되면 Worker.prototype은 name과 likes라는 두 가지 속성을 얻습니다. Worker 생성자가 호출되면 Person 생성자가 다시 호출되고 이번에는 인스턴스 속성 name과 likes가 직접 생성됩니다. , 프로토타입에서 동일한 이름을 가진 두 개의 속성을 다루고 있습니다.

5 프로토타입 상속

다음 객체 함수는 Douglas Crockford의 기사에 기록되었습니다. 객체 함수 내에서 임시 생성자가 먼저 생성된 다음 전달된 객체가 이 생성자의 프로토타입으로 사용되고 마지막으로 이 임시 유형의 새 인스턴스가 반환됩니다. 기본적으로 object()는 전달된 객체의 얕은 복사본을 수행합니다. 이 상속 방법은 상위 유형의 속성과 메서드를 하위 유형에 복사한 다음 해당 속성과 메서드를 하위 유형에 추가하는 것과 같습니다.
이 방법은 참조 유형 값의 속성도 공유합니다.

function object(o){
  function F(){}
  F.prototype = o;
  return new F();
}

let Superhero = {
  name: 'Avenger',
  skills: [],
  sayName: function () {
    console.log(this.name)
  }
}

let IronMan = object(Superhero)
IronMan.name = 'Tony Stark'
IronMan.skills.push('fly')

let CaptainAmerica = object(Superhero)
CaptainAmerica.name = 'Steve Rogers'
CaptainAmerica.skills.push('shield')

IronMan.sayName() // Tony Stark
console.log(IronMan.skills) // [ 'fly', 'shield' ]

ES5는 프로토타입 상속을 표준화하기 위해 Object.create() 메서드를 사용합니다. 이 메서드는 두 가지 매개 변수, 즉 새 개체의 프로토타입으로 사용할 개체와 (선택적으로) 새 개체에 대한 추가 속성을 정의하는 개체를 허용합니다. Object.create()는 하나의 인수가 전달될 때 object() 메서드와 동일하게 동작합니다. Object.create() 메서드의 두 번째 매개 변수는 Object.defineProperties() 메서드의 두 번째 매개 변수와 형식이 동일합니다.

let CaptainAmerica = Object.create(Superhero, {
  name: {
    value: 'Steve Rogers',
    configurable: false
  }
})

6 기생 상속

기생 상속은 이해하기 쉽습니다. 이는 상속 프로세스를 캡슐화하는 팩토리 함수일 뿐입니다. 메서드는 객체에 직접 정의되므로 기생 상속으로 추가된 메서드는 재사용할 수 없습니다.

function inherit(parent){
  var clone = Object.create(parent)
  clone.name = 'hulk'
  clone.sayHi = function(){
    console.log("hi")
  }
  return clone
}

let Hulk = inherit(Superhero)

Hulk.sayName() // hulk
Hulk.sayHi() // hi

7 기생 결합 상속

앞서 언급했듯이 결합 상속은 js에서 가장 일반적으로 사용되는 상속 방법이지만 단점은 부모 클래스의 생성자가 두 번 호출된다는 것입니다. 기생 구성 상속은 이 문제를 해결할 수 있으며 참조 유형 값을 포함하는 객체에 대한 가장 이상적인 상속 방법으로 간주됩니다.
기생 결합 상속의 기본 아이디어는 하위 클래스의 프로토타입을 지정하기 위해 상위 클래스의 생성자를 호출할 필요가 없다는 것입니다. 필요한 것은 상위 클래스의 프로토타입 복사본뿐입니다. 기생 구성 상속은 생성자를 빌려 속성을 상속한 다음 기생 상속을 사용하여 상위 클래스의 프로토타입을 상속하는 것입니다.

아아아아

위 내용은 js의 상속 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.