js的继承

JavaScript在设计之初只是为了在浏览器中添加一点交互,但是在js中模仿了java 万物皆对象,所以必须有一种方式能够让对象之间的数据实产生关联,设计者便设计了一种Prototype的继承方式

壹、构造函数里面的继承

一、原型链继承

  1. 现在这里有一个动物构造函数
 function Animal() {
            this.specil = "动物";
        }
  1. 然后有一个猫的构造函数
    function Cat(name, color) {
            this.name = name;
            this.color = color;
        }

3.实例化

 var cat1 = new Cat('miaomiao', 'orange');

那么那么猫咪如何继承动物这一属性呢?

  • 我们知道构造函数的实例可以继承自其构造函数的prototype属性(隐式继承)
  • 这个prototype属性呢是一个object类型的空对象
  • 那么将动物 这一构造函数的实列绑定给 prototype则可以让cat 实现继承
// 现在这里有一个动物构造函数
function Animal() {
    this.specil = "动物";
}
// 然后有一个猫的构造函数
 function Cat(name, color) {
    this.name = name;
    this.color = color;
}
 // 那么猫咪如何继承动物这一属性
var cat1= new Cat('miaomiao','orange');
Cat.prototype = new Animal();
console.log(cat1.specil);

问题一:以上代码运行为undefinded

此问题的区别只有var cat1= new Cat('miaomiao','orange'); Cat.prototype = new Animal(); 这两行代码的顺序问题。(困扰一整天…)

  1. 先前的理解:Cat构造函数的实例要继承Animal的属性,那么cat1=new Cat先实例化,cat1这个对象中能继承其构造函数的原型对象。那么在下一步我们将Cat.prototypeAnimal构造函数绑定Cat.prototype=new Animal ,则Animal的原型对象中的属性可被Cat的原型对象继承。
    也就是两部:①cat1继承Cat原型,②Cat原型继承Animal…合情合理!
  2. 实际的方式:上面的理解大致正确,但忽略了一个重要的属性__proto__,将过程细分则会发现区别。
    ①:先实例化的后果:Cat实例对象想继承Animal的东西,直接讲Cat的原型变成Animal的实例就可以啦~
    毕竟cat1能继承Cat.prototype->Animal.prototype注意是因为cat1.__proto__得以继承一旦实例这个属性地址值就已经创建,后面并没有更改它的指向;
    在这里插入图片描述
    ②:所以,由于是隐式继承,我们不能先更改Cat.prototype的指向!

那么 这也是可行的 var dog1 = new Dog(‘boolding’, 1);
dog1.proto = new Animal();

  1. 总结:** 理解1.原型链,且明白继承关系是隐式继承。2.new操作符**

二 原型链继承的改进

由于需要不必要的new Animal 过程,既然实现继承Animal=继承Animal.prototype那么Cat.prototype=Animal.prototype能够节约内存

同样有有优点的同时,它有又有一个很大的缺陷:当我们修改Cat.prototype 时会影响到Animal的原型.
解决方案:创建一个temp空对象作为跳转.

所谓空对象并不是直接var temp={},然后temp=Animal.prototype;这并没有任何意义temp的地址同样指向了Animal原型地址!

function Temp() {

        }
        Temp.prototype = Animal.prototype;
        var dog1 = new Temp();
        console.log(dog1.specil); //animal
        Dog.prototype.color = 'red';
        console.log(Animal.prototype.color); //undefined

new 一个空对象实在是太香了(内存消耗很小);
最后一步封装成一个继承函数

function extend(Father, Son) {
            function Temp() {};
            Temp.prototype = Father.prototype;
            Son.prototype = new Temp();
            Son.prototype.constructor = Son;
        }

        function Animal() {

        }
        Animal.prototype.specil = "animal";

        function Cat(name) {
            this.name = name;
        }
        extend(Animal, Cat);
        var cat1 = new Cat("maomi");
        console.log(cat1.specil);

贰、非构造函数的继承

1.object函数

var animal = {
specil :"动物",
}
var cat = {
	name:"tom"
}
 function temp(){}
 temp.prototype = animal;
 cat = new temp();
 cat.name="tom"

2.浅拷贝

遍历对象属性一一赋值

    for (var i in animal) {
            cat[i] = animal[i];
        }
        console.log(cat);

随便想想问题都大的很.

深拷贝

循环遍历浅拷贝

        function deepCopy(a, b) {
            for (var i in b) {
                var a = a || {};
                if (typeof b[i] == "object") {
                    a[i] = b[i].constructor == Array ? [] : {};
                    deepCopy(a[i], b[i]);
                } else {
                    a[i] = b[i]
                }
            }
            return a;
        }

二者互不影响:在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值