JS基础知识 - 继承、原型与原型链的理解

13 篇文章 0 订阅

五条原型规则:

  1. 所有的引用类型(数组,对象,函数),都具有对象特性,即可自由扩展属性(除了null之外)(null是object类型,但不具备可扩展属性)
  2. 所有的引用类型(数组,对象,函数),都具有_proto_(隐式原型)属性,属性值是一个普通的对象
  3. 所有的函数,都有一个prototype(显式原型)属性,属性值是一个普通的对象
  4. 所有的引用类型(数组,对象,函数),_proto_属性值指向它的构造函数的 “prototype” 属性值
  5. 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_(即它的构造函数的prototype)中寻找
var obj = {}; obj.num = 100;
var arr = []; arr.num = 100;
function fun() {}; fun.num = 100;

console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fun.__proto__);
console.log(fun.prototype);

console.log(obj.__proto__ === Object.prototype);

在这里插入图片描述

下面举例说明(Student、Teacher 继承People类):

class People {
	// 构造函数
	constructor(name) {
		this.name = name;
	}
	eat = () => {
		console.log(
			`${this.name} eat something`
		)
	}
}

class Student extends People {
	constructor(name, number) {
		// 继承 People 的属性
		super(name)
		this.number = number;
	}
	sayHi = () => {
		console.log(
			`姓名:${this.name},学号:${this.number}`
		)
	}
}

class Teacher extends People {
	constructor(name, major) {
		super(name)
		this.major = major;
	}
	sayHi = () => {
		console.log(
			`姓名:${this.name},课程:${this.major}`
		)
	}
}

const Melody = new Student('Melody', 21);
console.log(Melody.name, Melody.number); // Melody 21
Melody.eat();  // Melody eat something
Melody.sayHi();  // 姓名:Melody,学号:21

const Coco = new Teacher('Coco', 'English');
console.log(Coco.name, Coco.major);  // Coco English
Coco.eat();  // Coco eat something
Coco.sayHi();  // 姓名:Coco,课程:English

原型 与 原型链 图解

1、原型关系:

  • 每个 class 都有显式原型 prototype
  • 每个实例都有隐式原型_proto_
  • 实例的 _proto_指向对应 class 的 prototype

2、基于原型的执行原则

  • 获取属性 xialuo.name 或执行方法 xialuo.sayHi() 时
  • 先在自身属性和方法中寻找
  • 如果找不到则自动去_proto_中查找

3、原型图解
在这里插入图片描述
4、原型链图解
在这里插入图片描述

写一个贴近实际开发原型链继承的例子

function Elem(id) {
	this.elem = document.getElementById(id);
}

Elem.prototype.html = function (val) {
	var elem = this.elem;
	if (val) {
		elem.innerHTML = val;
		return this  // 链式操作
	} else {
		return elem.innerHTML;
	}
}

Elem.prototype.on = function (type, fn) {
	var elem = this.elem;
	elem.addEventListener(type, fn);
	return this;  //链式操作
}

var div1 = new Elem('mainBox');
// console.log(div1.html())
div1.html('<p>hello imooc</p>').on('click', function() {
	alert('clicked');
}).html('<p>javascript</p>');

补充:

ES6 引入了 Class(类)这个概念作为对象的模板。通过 class 关键字可以定义类。

  • constructor 方法是类的默认方法,通过 new 命令生成对象实例时自动调用该方法。一个类必须有 constructor 方法,如果没有显式定义,一个空的 constructor 方法会被默认添加。
  • 类必须使用 new 来调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用 new 也可以执行。
  • 类不存在变量提升(hoist),这一点与ES5完全不同。
  • Class 可以通过 extends 关键字实现继承
  • 子类必须在 constructor 方法中调用 super 方法,否则新建实例时会报错。这是因为子类没有自己的 this 对象,而是继承父类的 this 对象,然后对其进行加工。如果不调用 super 方法,子类就得不到 this 对象。
  • ES5 的继承实质是先创造子类的实例对象 this,然后再将父类的方法添加到 this 上面(People.apply(this)。
  • ES6 的继承机制完全不同,实质是先创造父类的实例对象 this(所以必须先调用 super 方法),然后再用子类的构造函数修改 this。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值