类分为 私有属性 公有属性 静态方法
使用对象方式,继承公有属性
let obj2 = {
age: 9,
name:'jw'
};
let obj = {
name:'zfpx',
getPName(){ // 可以通过super关键字获取到父属性
return super.name
},
__proto__:obj2
}
console.log(obj.getPName());
复制代码
只继承公有属性
Child.prototype.__proto__ = Parent.prototype;
复制代码
Object.setPrototypeOf(Child.prototype, Parent.prototype)
复制代码
上面两个等价,一个是es5一个是es6
只继承共有属性
Child.prototype = Object.create(Parent.prototype,{constructor:{value:Child}});
let child = new Child;
child.smoking();
console.log(child.constructor);
复制代码
实现原理:
function create(parentPrototype,props){
function Fn() {}
Fn.prototype = parentPrototype;
let fn = new Fn();
for(let key in props){
Object.defineProperty(fn, key, {
...props[key],
enumerable:true //不加这句枚举不出来child.constructor(undefined)
});
}
return fn;
}
// defineProperty中加了set get就不能加 writable和value了。
Child.prototype = create(Parent.prototype,{constructor:{value:Child}});
let child = new Child();
console.log(child.constructor);
复制代码
只继承私有属性 再子类中调用父类的方法即可 Parent.call(this)
function Parent(){
this.parent = 'parent';
}
Parent.prototype.smoking = function () {
console.log('吸烟')
}
function Child(){
Parent.call(this)
}
console.log(new Child().parent)
复制代码
child继承父类的所有的属性
function Parent(){
this.parent = 'parent';
}
Parent.prototype.smoking = function () {
console.log('吸烟')
}
function Child(){}
Child.prototype = new Parent;
let child = new Child();
Child.prototype.eat = function () {
console.log('吃')
}
console.log(child.parent)
console.log(child.smoking)
child.__proto__.eat();
console.log(child.__proto__=== Child.prototype)
console.log(Child.prototype.constructor === Child)
复制代码
为了追本溯源, 我顺便研究了new运算符具体干了什么?发现其实很简单,就干了三件事情.
var obj = {};
obj.__proto__ = F.prototype;
F.call(obj);
复制代码
第一行,我们创建了一个空对象obj;
第二行,我们将这个空对象的proto成员指向了F函数对象prototype成员对象;
第三行,我们将F函数对象的this指针替换成obj,然后再调用F函数.
我们可以这么理解: 以 new 操作符调用构造函数的时候,函数内部实际上发生以下变化:
1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
2、属性和方法被加入到 this 引用的对象中。
3、新创建的对象由 this 所引用,并且最后隐式的返回 this
function Otaku (name, age) {
this.name = name;
this.age = age;
this.habit = 'Games';
}
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () {
console.log('I am ' + this.name);
}
// 模拟new
function objectFactory() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);//对返回指值做处理,如果是引用对象则返回对象,如果是基本类型则忽略返回值,依然返回对象obj
return typeof ret === 'object' ? ret : obj;
};
var person = objectFactory(Otaku, 'Kevin', '18')
console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // 60
person.sayYourName(); // I am Kevin
复制代码
es6中的class继承公有属性和私有属性和静态方法
class Child extends Parent{ // 要求继承父亲的私有和有公有
constructor(){
super(); // Parent.call(this);
this.age = 9; // 私有属性
}
static a(){ // 属于类上的方法
return 1;
}
smoking(){ // 原型上的方法
console.log('smoking')
}
}
let child = new Child();
复制代码