struggleForLife

Sometimes your whole life boils down to one insane move.

导航

详聊js中的原型/原型链

先以一段简单的代码为例:
function Dog(params){
    this.name = param.name;
    this.age = param.age;
    this.bark = function(){
        console.log("汪汪汪!!!");
    };
}
var wc = new Dog({name:"旺财",age:3});
 
 
console.log(Dog.prototype)函数的原型属性
在上面这段代码里,Dog是构造函数(区别普遍函数,构造函数一般大写);wc是构造函数Dog的实例对象。 
那么我们说:当构造函数创建时,会存在一个神秘对象。构造函数的prototype属性(保存着该构造函数的方法和属性)指向该神秘对象,实例化对象的__proto__会指向该神秘对象。
这个神秘对象就是原型。 
wc.__proto__ == Dog.prototype == 原型所在的地址 
下图描述了这种关系: 
构造函数有原型属性,实例对象有原型继承 

原型的两种使用方式

前面说过,我们一旦定义一个函数对象,系统会自动给这个函数对象附上原型属性prototype,这是默认原型链结构

沿用默认原型链结构

Dog.prototype.bark = function(){ console.log("汪汪汪!!!"); }
这样子做,只是给Dog.prototype新添加了一个方法bark,没有破坏默认原型链结构
替换默认原型链结构
Dog.prototype = {
    bark:function(){
    console.log("汪汪汪!!!");
    }
}
这样子做,Dog.prototype指向了新的内存地址,丢失了默认原型链结构的一些默认方法,比如constructor 
下图说明了这两种方式的区别: 

原型的作用

原型的作用是为了实现继承  提高代码的复用
同样的,我们看一段代码:
function Dog(param){
    this.name = param.name;
    this.age = param.age;
    this.bark = function(){
        console.log("汪汪汪!!!");
    };
}
var wc = new Dog({name:"旺财",age:3});
var dh = new Dog({name:"大黄",age:2});
同样的,我们看一下内存分析图: 
console.log(wc.bark == dh.bark);//结果为false
把公有的方法存放在构造函数的原型中,实例对象本身并不存放该方法。这样子做,不论构造函数创建多少个实例,该公有方法始终只存在一个。 
这大大减少了内存的浪费
也许有人会问:在你的图上面wc和dh并没有bark方法,那么它们怎么能调用Dog.prototype里的bark方法?
原因就是js的原型继承特性,在后面谈到原型链的时候会做详细的探讨
 
也许有人会问:既然把公有方法都放在构造函数的原型属性里能节省内存,那么为什么不把name,age等属性也都放在里面呢?
这样做是不对的,对象有共性和特性。比如人都会吃饭睡觉,这是共性。但不同的人姓名年龄不同,这是特性。我们把共性放在原型里,只维护一个。但是特性要放在构造函数里

原型链结构

前面已经说了原型的作用是为了实现继承,提高代码的复用。那么原型实现继承的方法是什么呢?使用原型链! 
何为继承?子类把父类的方法拿来自己用。 
举个栗子:动物会吃饭睡觉,狗继承自动物,于是狗也会了吃饭睡觉;狗会吠叫,旺财和大黄继承自狗,于是旺财也会吠叫 
于是旺财—->狗—->动物就形成了一条链,js原型也有一条类似的链叫做原型链
这条链的原则是:A是B的构造函数 那么(实例化对象__proto__)B.__proto__ == A.prototype;prototype保存着该函数的属性和方法
如上诉的代码:Dog是wc的构造函数 那么wc.__proto__ == Dog.prototype,wc可以使用Dog.prototype里的属性和方法
我们再往上找找原型链吧!
Dog.prototype.__proto__ 是什么? 因为Dog.prototype是Obejct对象,所以Dog.prototype.__proto__ == Object.prototype
Dog.__proto__ 是什么?因为Dog是构造函数,是Function对象,所以Dog.__proto__ == Function.prototype
我们不妨画一下上面的原型链示意图:
Function和Object
这两位都是大佬级的角色了:Function是一切函数的起始,Object是一切对象的起始,他们怎么干一架呢?
    
1.Object也是一个构造函数,只要是函数都是Function的实例,所以:Object.__proto__ == Function.prototype
2.Function也是一个构造函数,所以: Function.__proto__ == Function.prototype
3.Function.prototype是一个”对象?”,所以:Function.prototype.__proto__ == Object.prototype
4.Object.prototype.__proto__ == null
这里有一个巨坑:typeof Function.prototype 结果是function 我也不知道为什么,知道原因的大神请不吝赐教^-^

posted on 2019-08-03 15:30  struggleForLife  阅读(215)  评论(0编辑  收藏  举报