JavaScript之原型对象学习总结

一、原型是什么?
男孩子应该不少人都玩过经典单机游戏《虐杀原型》,说实话,也是这款游戏让我对单机游戏情有独钟,游戏的剧情设定,人物刻画以及游戏本身的精彩,哈哈,意犹未尽。
转入正题,游戏的大致剧情,主角Alex(好像是这个名字)是一名退伍军人,后来被军方某神秘生化实验室抓去,做了一些特殊的二次改造,后来拥有超凡能力,后来家人被杀。Alex便开始追杀凶手,凶手正是Alex的“原型”,一个 big boss,是这个家伙给了Alex身上的许多改造和特性,所以Alex才拥有如此巨大的能力。
JavaScript的原型也是一样的,比如我们在创建一个对象,如函数(函数也是对象)时,js就会在内部为该对象创建一个原型属性,原型属性指向函数的原型,即原型对象。这个原型对象与这个函数(下文统称源对象)的关系可以理解为Alex之与Big Boss。
原型对象在默认情况下,会自动获得一个constructor属性,这个属性里边藏有一个指向自定义函数的指针,比如

function Person() {};
Person.prototype = {
    name:"zhangsan",
    age:21,
    job:"nurse",
    say:function () {
        alert(this.name);
    }
}

Person.prototype.constructor === Person 这个构造函数。如果将该构造函数实例化之后,如:var zhangsan = new Person(); 这个zhangsan实例内部也会包含一个指向构造函数的原型对象的指针–[[ Prototype]] ,样子很奇怪,因为js脚本无法访问,chrome和firefox ,Safari 里的控制台里经常看见一个proto 就是指的是实例对象和原型对象之间的链接–[[Prototype]]
为了理解prototype 、constructor、实例、原型、构造函数之间的关系,自己画的示意图如下:
这里写图片描述

二、原型与in操作符
使用原型模式创建对象的时候,往往原型上有很多的属性。而在实例化对象之后,实例对象也可以添加属性。众多的属性究竟哪些属性是原型的,哪些是属于实例的。因此in操作符主要用来判断属性的宿主和迭代属性。
1. in操作符:不管是属性是属于原型还是实例,只要能访问到,就返回true,否则返回false;
如:

function Person () {};
Person.prototype = {
    constructor:Person;
    name:'zhangsan',
    age:21,
    job:'teacher'
}
var zhangsan = new Person();
alert('name' in zhangsan) //true

zhangsan.name = 'vin',
alert('name' in zhangsan)  //同样返回true,即使是实例添加的属性

in 操作符与hasOwnProperty() 函数搭配可判断属性是否是原型属性:

function hasProtoPro(obj,prop) {
    return !obj.hasOwnProperty(prop) && prop in obj;
}

2 for ( var prop in obj) 循环对象的可访问的,而且是可枚举的属性。同样,不管是原型属性还是实例属性。

赠送两个函数:
Object.keys() 获取对象所有可枚举的属性名,返回字符串数组;
Object.getOwnPropertyNames() 获取对象所有实例属性,不论是否可枚举;

三、原型的动态性
理解:一句话,对原型对象的属性和方法的所有修改,都可以立刻反映在实例对象上。
言外之意,如果重写原型对象,实例和新原型对象没有任何“血缘关系”,好比,儿子和继父,虽然伦理上也是父亲,但实质上已经“重写”了父亲,然而,儿子和亲父的血缘关系依旧,反映在原型对象的重写问题上,则是实例对象和旧原型对象依然彼此连接,引用的依然是最初的原型。
如:

function Person() {};
var lisi = new Person();
//重写原型对象
Person.prototype = {
        name:"zhangsan",
        age:21,
        job:"nurse",
        say:function () {
            alert(this.name);
        }
    }
lisi.say()  //fatal error 

四、原型模式创建对象的问题
一句话,正是其把所有属性和方法都放在原型对象上,这样换来的“共享精神”出现了引用类型的属性出现引用悖论。
代码奉上:

function Person() {};
Person.prototype = {
        name:"zhangsan",
        age:21,
        wife:['w1','w2','w3']
    }
var zhangsan = new Person();
zhangsan.wife.push('w4');
alert(zhangsan.wife)  //['w1','w2','w3','w4']

var lisi = new Person();
alert(lisi.wife)  //['w1','w2','w3','w4']

zhangsan 纳入的小妾w4 ,同时也变成了lisi的小妾。乱套了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值