JS中动态原型模式的理解

动态原型模式是由构造函数和原型模式组合而成的,那么构造函数是怎样的呢:

function Box(name){
        this.name = name;
        this.call = function(){
            alert('your name is '+ this.name)
        }
   }
var box = new Box('obama');

这是一个典型的构造函数,通过使用new函数,实例化一个box对象,那么为什么可以通过使用new操作符实例化对象呢,其实在使用new操作符的同时,系统会执行以下操作;

var box = new Object();
box.__proto__ = Box.prototype;
Box.call(box);
//执行函数代码
return box;

首先默认生成一个对象,继承构造函数Box的原型,然后把函数的作用域绑定在这个对象上,在执行函数,最后返回这个对象,因此每个实例对象都是一个独立的对象,我们知道每个对象都是不相等的;

var box1 = new Box('a');
var box2 = new box('a');
box1.call == box2.call             //false

原型模式中,

function Bar(){};
Bar.prototype = {
        constructor:Box,
        age:100,
        call:function(){
            alert('your age is' + this.age)
        }
    }

我们都知道使用字面量的写法,会默认生成Object对象,因此要强制把constructor属性指向Bar,执行的过程是先看自身有没有这个属性,有就执行,不管原型里是否还有,如果没有就继续查找原型,有就执行,没有就报错,如何判断是自身属性还是原型里的属性呢;

var bar = new Bar();
bar.name = 'obama';
bar.hasOwnProperty('name');        //true
//hasOwnProperty 只会判断自身是否有这个属性,原型是否有无法判断;
'name' in bar;            //true
// in这个方法更近一步能判断不管自身还是原型有属性(当然是可以枚举的属性)
//通过这两个方法我们可以判断原型中是否有属性
function isProperty(object,property){
        return !object.hasOwnProperty(property) && (property in object);
    }

重点!!原型是会重写的,这和JS里其他的对象一样,后面的会覆盖前面的,还有个问题是如果原型中修改属性,一个实例对象就会改写这个值,导致其他的实例对象都会改变!!

function Box(){
}
Box.prototype = {
    constructor:Box,
    boxs:['box1','box2','box3'],
    name:'bigBox'
}
var box1 = new Box();
var box2 = new Box();
box1.name = 'first box';
console.log(box1.name);        //'first box'
console.log(box2.name);        //'bigbox'

box1.boxs.push('box4');

console.log(box1.boxs);        //["box1", "box2", "box3", "box4"]
console.log(box2.boxs);         //["box1", "box2", "box3", "box4"]

很难理解为什么box1修改name属性就不会重写原型,而修改boxs属性就会重写原型,两者的差别就在于一个是赋值,一个是查找,打个比方,
a向b借了100元,那么a就得到了100元,不是a的父亲,爷爷得到了100元,所以赋值即给a添加不论是属性还是方法收益的只有a,不会给a的父亲,爷爷其他人也赋值,但是如果b找a 还的话,如果找不到a就可以找a 的父亲爷爷等其他人,这个意思是是说,只要是赋值,就只作用在赋值对象上,但是查找就不同,可以一直追溯到其他人,上面的例子,
box1.boxs.push(''box4'),可以这么理解,首先是查找,box1.boxs,不然如何push呢,自身属性没有,但是原型上有,有就OK直接操作push,但是这个操作是对象是所有对象共享的,所以一旦修改就改变了!
基于以上的问题,那么动态原型模式就是把共享的使用原型,不共享的使用构造函数,

function Box(){
    this.name:'bigBox';
    this.boxs = ["box1", "box2", "box3"];
};
Box.prototype = {
    constructor:Box,
    num:function(){
    console.log(this.boxs.length);
    }
}
//或者写在一起
function Box(){
     this.name:'bigBox',
     this.boxs = ["box1", "box2", "box3"];
    if(typeof this.run != 'function'){
        Box.prototype.num = function(){
             console.log(this.boxs.length);
        }
    } 
}
//因为构造函数执行时,里面的代码都会执行一遍,而原型有一个就行,不用每次都重复,所以仅在第一执行时生成一个原型,后面执行就不必在生成,所以就不会执行if包裹的函数,
//其次为什么不能再使用字面量的写法,我们都知道,使用构造函数其实是把new出来的对象作用域绑定在构造函数上,而字面量的写法,会重新生成一个新对象,就切断了两者的联系!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值