继承-子承父业
面向对象编程语言的三大特点:封装,继承,多态
hasOwnProperty使用:
1.语法:obj.hasOwnProperty(propname);
2.作用:判断propname属性是不是obj对象自己的;
3.hasOwnProperty来源:Object.prototype (Object的原型对象);
任何对象的原型链上都有Object.prototype,所以任何对象都可以调用hasOwnProperty方法
1.混入式继承
拷贝一个对象的所有属性和方法;
//需求:让p继承f的属性;
var f = {
car: '劳斯莱斯',
money: 1000000
};
var p = {
skill: '吃鸡'
};
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
//给p对象添加extend方法:
p.extend = function(obj) {
//for...in 循环会把对象原型链上可以被遍历的属性和方法都遍历到:
for (let key in obj) {
//使用hasOwnProperty方法,排除原型里的其他属性和方法:
if (obj.hasOwnProperty(key)) {
this[key] = obj[key];
}
}
};
p.extend(f);
console.log(p);
2.原型链继承
原理:构造函数创建的实例对象可以直接访问对应原型上的任意成员,即实例对象可以继承原型上的任意成员
方法一:手动给原型添加成员(麻烦)
function Person(name) {
this.name=name
}
Person.prototype.color='pink';
Person.prototype.render=function() {}
方法二: 原型替换
Person.prototype={
//constructor属性丢失,需手动添加
constructor:Person,
color:'red',
render:function() {}
}
var p=new Person();
//p实例对象可以访问到上面的的属性和方法
原型替换的缺点:会造成constructor属性的丢失;
原型替换前的原型链:
实例p=> Person.prrototype(默认原型)=>Object.prototype=>null
原型替换后的原型链:
p.__proto__.constructor不再指向Person,指向Object
p=>Person.prototype(新对象)=>Object.prototype(constructor指向Object)=>null
3. 混入+原型链继承
给构造函数的原型添加extend方法,遍历传入的对象,给实例对象添加可访问的属性和方法
let objSurper = {
eat: '肉肉',
hobby: ['吃饭', '睡觉', '打豆豆'],
skill: function() {
console.log('吃鸡');
}
};
function Person(name, money) {
this.name = name;
this.money = money;
}
//原型对象上添加extend方法:
Person.prototype.extend = function(obj) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
this[key] = obj[key];
}
}
};
Person.prototype.extend(objSurper);
let p = new Person('小小丫',10000);
console.dir(p);
4.经典继承
Object.create()
1.语法:var newObj=Object.create(obj);
2.作用:Object.create方法创建并返回一个空对象,空对象的原型是obj;
let obj = {
say: 'ok'
};
let newObj = Object.create(obj);
console.log(newObj); //{}
console.log(newObj.__proto__ == obj); //true