>웹 프론트엔드 >JS 튜토리얼 >JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석

JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석

WBOY
WBOY앞으로
2022-02-15 17:44:332128검색

이 기사는 생성자, 프로토타입 및 클래스 구문 설탕과 관련된 문제를 포함하여 javascript의 상속 및 프로토타입 체인에 대한 지식을 제공합니다.

JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석

자바스크립트의 상속과 프로토타입 체인에 대한 간략한 분석

1. 소개

자바스크립트의 상속과 프로토타입 체인은 제가 프론트엔드를 배우는 과정에서 접한 드물고 이해하기 어려운 부분입니다. . 여기에는 제가 알고 배운 내용을 모두 기록해 두었습니다. 여전히 어려움을 겪고 있는 형제들에게 작은 도움이 되기를 바랍니다. 여러분의 비판과 정정도 환영합니다.

2. 생성자

2.1 생성자의 인스턴스 멤버 및 정적 멤버

생성자는 인스턴스 멤버와 정적 멤버로 구성됩니다. 여기서 인스턴스 멤버는 함수 내부의 this 키워드를 통해 추가된 멤버입니다. 개체를 인스턴스화한 후 인스턴스화된 개체를 통해 액세스할 수 있는 반면 정적 멤버는 함수 자체에 추가된 멤버이며 생성자를 통해서만 액세스할 수 있습니다.

//创造一个构造函数let Father = function(name,age){
    //实例成员
    this.name = name;
    this.age = age;
    this.method = "我是一个实例成员";}
    //静态成员Father.like = "mother";
    //检验实例对象是否能够被构造函数直接访问console.log(Father.method);
    //undefinedconsole.log(Father.like);
    //mother
    //实例化一个对象let father = new Father("小王",27);
    //检验静态对象是否能够被实例化对象访问console.log(father.name);
    //小王console.log(father.age);
    //27console.log(father.like);
    //undefined

2.2 객체 인스턴스화 과정

new 키워드를 사용하면 생성자를 통해 인스턴스화된 객체를 구현할 수 있는데, 특정 인스턴스화 과정에서는 어떤 일이 발생할까요? 이는 대략 다음 단계로 나눌 수 있습니다.

(1) 빈 객체 son 만들기 {}

(2) son son.__proto__ = Father.prototypeson.__proto__ = Father.prototype

(3) 重新绑定this,使构造函数的this指向新对象 Father.call(this)

(4) 为新对象属性赋值 son.name

(5) 返回this return this,此时的新对象就拥有了构造函数的方法和属性了

一个小问题:所有实例化对象的方法都是共享的吗?

构造函数的方法分为两种,第一种为在函数内部直接定义的方法,第二种为通过原型添加的方法;

//函数内部直接定义的方法let Father = function(){
    this.read = function(){
        console.log("我是内部定义的read方法!");
    }}//通过JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석添加的方法Father.prototype.look = function(){
    console.log("我是通过JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석定义的look方法!");}
    //实例化对象进行检验let father1 = new Father();let father2 = new Father();
    father1.read();
    //我是内部定义的read方法!father2.read();
    //我是内部定义的read方法!console.log(father1.read === father2.read);
    //falsefather1.look();
    //我是通过JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석定义的look方法!father2.look();
    //我是通过JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석定义的look方法!console.log(father1.look === father2.look);
    /true

可以发现,函数内部直接定义的方法在每实例化一个新的对象以后,都会给这个方法分配一个新的内存空间,而通过原型添加的方法便会共享一个空间。

一个小问题:所有实例化对象的属性都是共享的吗?

不存在内存空间的问题,判断时看其值是否相同;

let Father = function(name){
    this.name = name;}let father1 = new Father("小王");
    let father2 = new Father("小红");
    console.log(father1.name === father2.name);
    //falselet father1 = new Father("小王");
    let father2 = new Father("小王");
    console.log(father1.name === father2.name);
    //true

因此我们可以总结一下定义构造函数的基本规则,即公共属性定义到构造函数里面,公共方法我们放到原型对象身上。

三、原型

3.1 什么是原型

Father.prototype 就是原型,它是一个对象,也可以称为原型对象。

3.2 原型的作用是什么

原型的作用,就是共享方法。

我们通过 Father.prototype.method 可以共享方法,不会反应开辟空间存储方法。

3.3 原型中的this指向哪儿

原型中this的指向是实例。

四、JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석

JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석本人感觉是一个对于初学者或者说是部分前端菜鸡(例如本人)来说特别难以理解的东西,为了让下面的部分更容易理解,这里强行先记住以下几点:

  1. __proto__是每个对象都有的属性,prototype是每个函数特有的方法;
  2. 每个对象的__proto__属性都会指向自身构造函数的prototype;
  3. constructor属性始终指向创建当前对象的构造函数;
  4. Function.__proto__ === Function.prototype;
  5. Object.prototype.__proto__ === null 也就是JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석的终点;

4.1 什么是JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석

原型与原型层层相链接的过程即为JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석。

4.2 JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석的应用

对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在每个对象都有__proto__

에 대한 프로토타입 체인 연결 준비 (3) 생성자의 this가 새 개체 Father.call(this)

를 가리키도록 이것을 다시 바인딩합니다.(4) 새 개체 속성 son.name에 값을 할당합니다.

JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석( 5) Return this return this 이때 새 객체는 생성자의 메서드와 속성을 갖게 됩니다.

작은 질문: 인스턴스화하는 메서드는 모두 있습니까? 공유된 객체?

함수를 구성하는 방법에는 두 가지가 있습니다. 첫 번째는 함수 내부에서 직접 정의한 메소드이고, 두 번째는 프로토타입을 통해 추가한 메소드입니다. 새 객체를 인스턴스화한 후 이 메서드에 새 메모리 공간이 할당되고 프로토타입을 통해 추가된 메서드는 동일한 공간을 공유합니다.

작은 질문: 인스턴스화된 모든 객체의 속성이 공유됩니까?

메모리 공간 문제는 없습니다. 판단할 때 값이 같은지 여부에 따라 다릅니다.

let Father = function(name){
    this.name = name;}let father = new Father("老王");console.log(father.__proto__ === Father.prototype);
    //true
    //验证上述说法中的第二条

그래서 생성자 정의에 대한 기본 규칙, 즉

공용 속성이 정의됩니다. 생성자에 있고 공용 메소드는 프로토타입 객체에 배치됩니다.

3. 프로토타입

🎜3.1 프로토타입이란 무엇입니까? 🎜🎜Father.prototype은 프로토타입 객체이며 프로토타입 객체라고도 합니다. 🎜🎜3.2 프로토타입의 역할은 무엇인가요?🎜🎜프로토타입의 역할은 방법을 공유하는 것입니다. 🎜🎜공간 저장 방식을 반영하지 않는 Father.prototype.method를 통해 메소드를 공유할 수 있습니다. 🎜🎜3.3 프로토타입의 이 항목은 어디를 가리킵니까? 🎜🎜프로토타입의 이 항목은 인스턴스를 가리킵니다. 🎜🎜🎜4. 프로토타입 체인 🎜🎜🎜 프로토타입 체인은 초보자나 일부 프런트엔드 초보자(나 같은)에게 특히 이해하기 어려운 부분이라고 생각합니다. 강제로 적용됩니다. 다음 사항을 기억하세요. 🎜
  1. __proto__는 각 객체의 속성이고, 프로토타입은 각 함수에 고유한 메서드입니다. __proto__ 속성은 자체 생성자의 프로토타입을 가리킵니다.
  2. 생성자 속성은 항상 현재 객체를 생성한 생성자를 가리킵니다. Function.__proto__ code> === Function.prototype;
  3. Object.prototype.__proto__ === null은 프로토타입 체인의 끝입니다.
  4. 🎜4.1 프로토타입 체인이란🎜🎜프로토타입과 프로토타입을 레이어별로 연결하는 과정이 프로토타입 체인입니다. 🎜🎜4.2 프로토타입 체인의 적용🎜🎜객체는 __proto__를 갖고 각 객체는 __proto__를 가지므로 생성자 프로토타입 프로토타입 객체의 속성과 메소드를 사용할 수 있습니다. 프로토타입의 존재 🎜
    function Star(name) {
    	this.name = name;
    	//(1)首先看obj对象身上是否有dance方法,如果有,则执行对象身上的方法
    	this.dance = function () {
    		console.log(this.name + '1');
    	}}//(2)如果没有dance方法,就去构造函数原型对象prototype身上去查找dance这个方法。Star.prototype.dance = function () {
    	console.log(this.name + '2');};
    	//(3)如果再没有dance方法,就去Object原型对象prototype身上去查找dance这个方法。Object.prototype.dance = function () {
    	console.log(this.name + '3');};
    	//(4)如果再没有,则会报错。let obj = new Star('小红');obj.dance();
    🎜4.3 프로토타입 체인 다이어그램🎜🎜🎜🎜🎜처음 몇 가지 사항을 종합해 보면 위 그림을 이해하는 데 큰 문제가 없을 것입니다. 그림에서 동그라미 친 부분은 끔찍한 프로토타입 체인입니다. 🎜🎜4.4 프로토타입 체인 검색 방법🎜
    function Star(name) {
    	this.name = name;}Star.prototype = {
        dance:function(){
        	console.log("重定义prototype");
    	}}Star.prototype.constructor = Star;
    🎜(1) 먼저 obj 객체에 댄스 메소드가 있는지 확인하세요. 그렇다면 해당 객체에 메소드를 실행하세요. 🎜🎜(2) 댄스 메소드가 없으면 생성자 프로토타입 객체 프로토타입으로 이동하여 댄스 메소드를 찾습니다. 🎜🎜(3) 댄스 방법이 없으면 객체 프로토타입 개체 프로토타입으로 이동하여 댄스 방법을 찾습니다. 🎜🎜(4) 더 이상 없으면 오류가 보고됩니다. 🎜
    一个小问题:在原型上添加方法需要注意的地方

    有两种添加方法,第一种为上面的写法,直接通过 构造函数.prototype.方法名 进行添加;第二种为重定义构造函数的prototype,但是此种情况会丢失掉原有的constructor构造器,所以一定要再连接回去,例子如下:

    function Star(name) {
    	this.name = name;}Star.prototype = {
        dance:function(){
        	console.log("重定义prototype");
    	}}Star.prototype.constructor = Star;

    另外,类似于Array、String这些内置的类是不能这么处理的。

    五、继承

    这里就长话短说,首先我们要明确继承需要继承哪些东西,在前文中我们提到了定义构造函数的基本规则,即**公共属性定义到构造函数里面,公共方法我们放到原型对象身上。**我们所需要继承的东西也不外乎就这二者,公共属性的继承可以通过call()或者apply()进行this的指向定义,而公共方法可以通过原型对象的赋值进行处理,因此我们很容易想到如下的方法:

    //定义一个父类function Father(name) {
    	this.name = name;}Father.prototype.dance = function () {
    	console.log('I am dancing');};//定义一个子类function Son(name, age) {
    	Father.call(this, name);
    	this.age = age;}//通过赋值的方法连接Son.prototype = Father.prototype;//为子类添加方法Son.prototype.sing = function () {
    	console.log('I am singing');};
    	let son = new Son('小红', 100);
    	//此时父类也被影响了console.log(Father.prototype) 
    	//{dance: ƒ, sing: ƒ, constructor: ƒ}

    很显然,当我们只想修改子类里面的方法时,显然上述方法不太合适;因此 我们可以尝试new一个新的父类出来,代码如下:

    function Father(name) {
    	this.name = name;}Father.prototype.dance = function () {
    	console.log('I am dancing');};function Son(name, age) {
    	Father.call(this, name);
    	this.age = age;}Son.prototype = new Father();Son.prototype.sing = function () {
    	console.log('I am singing');};let son = new Son('小红', 100);console.log(Father.prototype) 
    	//{dance: ƒ, constructor: ƒ}

    六、class语法糖

    对于以前了解过面向对象编程的程序员来讲,上述关于继承的写法属实让人有些难以接受,因此在es6里面新增了一个语法糖来更方便更便捷地书写继承,这里就直接上代码了;

    class Father {
    	constructor(name) {
    		this.name = name;
    	}
    	dance() {
    		console.log("我是" + this.name + ",我今年" + this.age + "岁," + "我在跳舞");
    	}}class Son extends Father {
    	constructor(name, age) {
    		super(name);
    		this.age = age;
    	}
    	sing() {
    		console.log("我是" + this.name + ",我今年" + this.age + "岁," + "我在唱歌");
    	}}let obj = new Son('小红', 19);
    	obj.sing();obj.dance();

    分析一下上面代码,首先一个类(构造函数)里面依旧为两部分,即公共属性和公共方法,constructor() 里面存放了该构造函数的公共属性,后面接着的便是公共方法,extends 关键字表示继承的是哪个类,super() 便是将里面父类里面相应的公共属性拿出来,这样看下来便可以将代码规整许多。

    相关推荐:javascript学习教程

위 내용은 JavaScript 상속 및 프로토타입 체인에 대한 간략한 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제