我爱编程

JS高级 03

2018-05-25  本文已影响0人  _MARPTS

JS实现继承的方式

属性继承

var obj = {
    name :'zs'
    ,age:20,
    friends:['小明','小红']
}

var obj1 = {};

for(var key in obj){
    obj1[key] = obj[key]
}

obj1.friends.push('老王')

console.log(obj1);
console.log(obj);

// 如果属性是引用类型的数据,子对象和父对象会共享同一份数据,修改其中一个,会影响另外一个

var obj = {name:'zs'};
var obj1 = {age:20};

var o = {};

// 第一个参数:目标对象
//后面参数:要拷贝属性的对象
Object.assign(o,obj,obj1);

console.log(o);

原型式继承

特点:

  • 1.不能获取实例属性和实例方法,只能获取父构造函数原型对象的属性和方法
  • 2.无法修正构造器属性,默认指向父构造函数

设置子构造函数的原型对象是父构造函数的原型对象---->原型式继承

function Person() {
    
}
// 利用构造函数创建出来的对象可以使用原型对象的属性和方法
Person.prototype.des = 'des';
var p1 = new Person();
console.log(p1.des);
//1.提供一个父构造函数
function Person() {
    this.name = '默认';
}
Person.prototype.des = 'aaa';
//2.提供一个子构造函数
function stu() {
    
}
// 设置子构造函数的原型对象是父构造函数的原型对象---->原型式继承
stu.prototype = Person.prototype;

var s1 = new Stu();
console.log(s1.des);
扩展内置对象
    // 需求 arr1有一个des属性和logDes方法
    var  arr1 = [1,2,3,4];
    arr1.des = 'des';
    arr1.logDes = function () {
        console.log(this.des);
    }
    
    console.loe(arr1.des);
    
    var arr2 = [5,6,7];
    arr2.des = 'des';
    arr2.logDes = function () {
        console.log(this.des);
    }
    
    // 需求  所有数组都添加一个des属性和logDes方法
    Array.prototype.des = 'des';
    Array.prototype.logDes = function() {
        console.log(this.des);
    }
    var arr3 = [3,4,5];
    var arr4 = [6,7,8];
    console.log(arr3.des);
    console.log(arr4.des);

    //通过这种方式确实可以扩展内置对象,但是不建议这样做
    // 因为在公司开发中,很可能是多人一起开发,而且项目的代码量可能非常多
    //如果人人都通过这种方式扩展内置对象,不方便项目日后的维护,很容易出现方法被覆盖的问题
安全的扩展内置对象
function MyArray() {
    
}
MyArray.prototype = []//new Array();
MyArray.prototype.des = 'des';
MyArray.prototype.logDes = function (){
console.log(this.des);
}

var myarr1 = new MyArray();
myarr1.push('小明');
console.log(myarr1);
console.log(myarr1.des);

;

原型链(画图理解)

原型链中属性的访问原则(就近原则)

原型链继承

特点

  • 1.对比原型式继承,他还可以继承父构造函数的实例属性,方法和原型对象
  • 2.对比原型式继承,他可以修正构造器属性constructor
//1.提供一个父构造函数和子构造函数
function Person() {
    this.name = '默认';
}
Person.prototype.des = 'des';

function Stu() {
    
}
// 2.原型链继承
Stu.prototype = new Person();

var s1 = new Stu();
console.log(s1.des);//des
console.log(s1.name);//默认

原型链注意点
原型链继承的问题

Object.create()方法

    var obj = {name:'zs',age:20};
    
    //创建一个新的对象,并设置这个对象的原型对象
    var o = Object.create(obj);
    console.log(o.name);
call和apply函数
var zs = {
    name:'zs',
    showName : function (p1,p2){
        console.log(this.name,p1,p2)
    }
}

var ls = {
    name: 'ls'
}

zs.showNam('憨厚','耿直');
// 无法直接访问
//ls.showNam('智商高','情商低') // 报错

zs.showName.call(ls,'智商高','情商低')
zs.showName.apply(ls,['智商高','情商低'])
借用构造函数继承 | 经典继承 | 伪对象继承
    function Person(name,age){
        this.name = name;
        this.age = age;
    }
     Person.prototype.des= 'des';
    
    function stu(num,name,age){
        this.num = num;
        // 借用构造函数继承
        Person.call(this,name,age)
    }

    var s1 = new stu(10086,'zs',20);
    var s2 = new stu(1002,'ls',22);
    
    console.log(s1);
    console.log(s2);
    
    console.log(s1.des);
    console.log(s2.des);
组成继承

特点(利用借用构造函数继承)

  • 1.解决了原型链参数传递给父构造函数的问题
  • 2.解决了原型链继承所得的原型对象的数据共享问题
    function Person(name){
        this.name = name;
    }
    Person.prototype.des= 'des';
    
    function stu(num,name){
        this.num = num;
        // 借用构造函数继承
        Person.call(this,name)
    }
    
    // 原型式继承
    Stu.prototype = Person.prototype
    
    // 原型链继承
    Stu.prototype = new Person()
    Stu.prototype.constructor = stu;
    
    var s1 = new stu(10086,'zs');
    
    console.log(s1.name);
    console.log(s1.des);
深拷贝和浅拷贝
Array.isArray()
上一篇 下一篇

猜你喜欢

热点阅读