js 中的继承是原型的继承,而不是改变构造函数的原型
1、继承是原型的继承
*通过设置__proto__实现继承
function User() {}
User.prototype.name = function () {
console.log("user.name");
};
function Admin() {}
Admin.prototype.__proto__ = User.prototype;
Admin.prototype.role = function () {
console.log("admin.role");
};
let a = new Admin();
a.name(); //user.name
m.role(); //user.name
*通过Object.create实现继承
function User() {}
User.prototype.name = function () {
console.log("user.name");
};
function Admin() {}
//将User的prototype作为原型生成一个新对象,再将其赋值给Admin的prototype
Admin.prototype = Object.create(User.prototype);
Admin.prototype.role = function () {
console.log("admin.role");
};
let a = new Admin();
a.name(); //user.name
2、继承对 constructor 属性的影响
function User() { }
User.prototype.name = function () {
console.log('user.name');
}
function Admin() { }
//继承User
Admin.prototype = Object.create(User.prototype);
Admin.prototype.role = function () {
console.log('admin.role');
}
console.dir(Admin)//constructor 丢失
如下代码,a. __ proto __ 指向Admin.prototype ,但是Admin的prototype上没有constructor属性,所以就会延着原型链找到User.prototype的constructor,所以最后结果会输出 ture
let a = new Admin();
let b = new a.__proto__.constructor();
console.dir(b.__proto__ === User.prototype)//true
解决:
//继承User
Admin.prototype = Object.create(User.prototype);
//手动加上 constructor属性
Admin.prototype.constructor = Admin;
Admin.prototype.role = function () {
console.log('admin.role');
}
3、禁止 constructor 被遍历
...
let a = new Admin();
for (const key in a) {
console.log(key);
}
...
//继承User
Admin.prototype = Object.create(User.prototype);
Admin.prototype.constructor = Admin;
console.log(Object.getOwnPropertyDescriptors(Admin.prototype));
...
//继承User
Admin.prototype = Object.create(User.prototype);
//思路打开,换种方式继承
Object.defineProperty(Admin.prototype, 'constructor', {
value: Admin,
enumerable: false
})
4、方法重写与父级属性访问
function User() { }
User.prototype.show = function () {
console.log('user.name');
}
User.prototype.site = function () {
return 'hello'
}
function Admin() { }
//继承User
Admin.prototype = Object.create(User.prototype);
Admin.prototype.constructor = Admin;
//重写父类show方法
Admin.prototype.show = function () {
//父级属性访问
console.log(User.prototype.site() + 'admin.show')
}
let a = new Admin();
a.show();
5、面向对象的多态
function User() { }
User.prototype.show = function () {
console.log(this.desc());
}
function Admin() { }
Admin.prototype = Object.create(User.prototype)
Admin.prototype.desc = function () {
return 'admin'
}
function Member() { }
Member.prototype = Object.create(User.prototype);
Member.prototype.desc = function () {
return 'member'
}
for (const obj of [new Admin(), new Member()]) {
obj.show()
}
6、使用父类构造函数初始属性
function User(name, age) {
this.name = name;
this.age = age;
}
User.prototype.show = function () {
console.log(this.name, this.age);
};
function Admin(...args) {
User.apply(this, args);
// User.call(this, name, age)
}
Admin.prototype = Object.create(User.prototype);
let zs = new Admin('zs', 10);
zs.show();
7、使用原型工厂封装继承
//封装继承
function extend(sub, sup) {
sub.prototype = Object.create(sup.prototype);
Object.defineProperty(sub.prototype, 'constructor', {
value: sub,
enumerable: false
})
}
function User(name, age) {
this.name = name;
this.age = age;
}
User.prototype.show = function () {
console.log(this.name, this.age);
}
function Admin(...args) {
User.apply(this,args);
}
//继承
extend(Admin, User);
let admin = new Admin('张三', 19);
admin.show();//张三 19
8、对象工厂派生对象并实现继承
function User(name, age) {
this.name = name;
this.age = age;
}
User.prototype.show = function () {
console.log(this.name, this.age);
}
function admin(name, age) {
// 1.继承
// const instance = {};
// instance.__proto__ = User.prototype;
// 2.继承
const instance = Object.create(User.prototype);
User.call(instance, name, age);
instance.role = function () {
console.log('role');
}
return instance;
}
let obj = admin('张三', 20);
obj.role();
9、使用mixin实现多继承
function extend(sub, sup) {
sub.prototype = Object.create(sup.prototype);
Object.defineProperty(sub.prototype, 'constructor', {
value: sub,
enumerable: false
})
}
const Address = {
getAddress() {
console.log('获取地址');
}
}
const Request = {
ajax() {
console.log('请求');
}
}
function User(name, age) {
this.name = name;
this.age = age;
}
User.prototype.show = function () {
console.log(this.name, this.age);
}
function Admin(name, age) {
User.call(this, name, age)
}
//继承
extend(Admin, User);
Admin.prototype = Object.assign(Admin.prototype, Request,Address);
let admin = new Admin('张三', 19);
admin.ajax()
admin.getAddress()
10、mixin内部继承与super关键字
...
const Address = {
__proto__: Request,
getAddress() {
console.log(super.ajax() + '获取地址');
}
}