概念
一:继承的概念:
-
1、在原有的类的基础上快速增加新的功能
-
2、不影响到原来的类,也不改变原来类的代码,方便对于功能的扩展
-
3、继承是一种创建新类的方式,新建的类可以继承一个或多个类。
-
4、新建的类称为派生类(子)类,之前存在的类称为基(父)类
记忆方法:基就是地基是盖房子的第一步,所以是之前的就存在的,派生就是派生出新的被,肯定是后出现的,所以叫派生,在原来的类上派生出新的类,那么有原来的类才有后来派生的,有父亲才能有儿子,儿子是父亲生下来的,所以也可以叫父类和子类
涉及到的api
1、Object.setPrototypeOf(hd, parent);//创建 Object.getPrototypeOf(hd)//获取
1、创建极简对象
let xj = Object.create(null, { name: { value: "向军" }} );
2、
let hd = {};
let parent = { name: "parent" };
Object.setPrototypeOf(hd, parent);
console.log(hd);
console.log(Object.getPrototypeOf(hd));
Object.create()不会继承大Boss Object上的原型,它会把你传入的第一个参数对象作为原型来继承,第二个参数是关于它自己的自有属性的描述。
而new 操作符以及对象字面量创建方式都会继承大老板 Object的原型上的属性方法。
call也不会继承function的原型上的属性方法,只是实例化function构造函数
new一个函数会返回什么?
new操作符在执行过程中会改变this的指向,所以在了解new操作符之前,我们先解释一下this的用法。
function Cat (name, age)
{
this.name = name;
this.age = age;//没写return 就是return this
}
console.1og (new cat('mi aomiao', 18));
// Cat [name: "miaomiao", age: 18]
输出的结果中包含了name与age的信息。事实上我们并未通过return返回任何值,为什么输出的信息中会包含name和age属性呢?其中起作用的就是this这个关键字了。
function Cat (name, age) {
var Cat = {Cat.name = name Cat.age = age;}
return Cat;
}
console.1og (new Cat('mi aomi ao'18), 18)
// Cat [name: "miaomiao", age: 18]
结果一样
但是这样子的对象没有绑定原型的,要写下面的代码
obj._ _proto_ _ = Cat.prototype;
实现继承的几种方法
1、原型链继承
原型链继承的主要思想是:重写子类的prototype属性,将其指向父类的实例。
Cat.prototype = new Animal();
。
2、构造器继承
将父类的实例的属性和函数绑定到子类的this上\
function Cat(name) {
// 核心,通过call()函数实现Animal的实例的属性和函数的继承
Animal.call(this); this.name = name || 'tom';
}
3、(原型链+构造器 继承)extends
function Super(name, age) {//父类,超类
this.name = name;
this.age = age;
}
Object.assign(Super.prototype, {
sleep() {
console.log(`${this.name} is sleeping!`);
}
})
//子类
function Sub(name, age, gender) {
Super.call(this, name, age);
//以调用父类构造函数的形式,得到执行结果,将this绑定为当前的实例对象
//普通调用时,this的指向window而不是当前实例对象,所以使用方法借用,绑定this的指向
this.gender = gender;
Sub.prototype = Object.create(Super.prototype);
//以父类的prototype为原型,创建一个空对象,替换子类的prototype
//由于空对象身上没有constructor引用,赋值
Sub.prototype.constructor = Sub;
//自己的方法
Object.assign(Sub.prototype, {
eat() {
console.log(`${this.name} is eating!`);
}
});
let sub1 = new Sub("zs", 18, "male");
// sub1.constructor===>fn Sub//sub1通过自己身上的__proto__指向创建它的类的原型对象
//Sub.prototype,prototype身上有它所在的构造函数的引用constructor
//sub1.__proto__.constructor====>fn Sub
}
为什么子类构造器中要先执行super
使用 Mixin 实现多继承,
Object.assign(Admin.prototype, Request, Credit);
function extend(sub, sup) {
sub.prototype = Object.create(sup.prototype);
sub.prototype.constructor = sub;
}
function User(name, age) {
this.name = name;
this.age = age;
}
User.prototype.show = function() {
console.log(this.name, this.age);
};
const Credit = {
total() {
console.log("统计积分");
}
};
const Request = {
ajax() {
console.log("请求后台");
}
};
function Admin(...args) {
User.apply(this, args);
}//“相当于复制的方式”拿到user的属性给创造出来的Admin实例
extend(Admin, User);
Object.assign(Admin.prototype, Request, Credit);
let hd = new Admin("向军", 19);
hd.show();
hd.total(); //统计积分
hd.ajax(); //请求后台
应用
1、给普通对象添加Object原型上的方法
内置对象.prototype.方法.call(要处理的对象, item => {
return item.hasAttribute("class");//原来例子是过滤节点,含有class属性的
})
2、为 Object 原型对象添加方法,
将影响所有函数
<body>
<button onclick="this.hide()">后盾人</button>
</body>
<script>
Object.prototype.hide = function() {
this.style.display = "none";
};
</script>
原型链关系图
1、对象有__proto__ 函数有prototype
2、对象由函数产生
3、对象的__proto__ 指向 函数的prototype
所有原型对象都是Object构造函数生成的,指父。
原型对象--》父Objiect.proty 构造函数都--》Func提on。prototype【额
构造函数的“构造能力”怎么来的?Function.prototype传承下来的额
强语言的类的基本特征:抽象、封装、继承、多态 js基于原型的对象机制,也可以达到类的基本特征:抽象、封装、继承、多态
遇到的问题
同样是new,构造函数产生的,构造函数里面的方法不见了,类里面的方法放到了原型里面"__ proto __")。(但为什么类不能 在 控制台打印出来)
因为忘记加this.了!!