《JS高级程序设计》第6章读书笔记:创建对象(三)再探原型

《JS高级程序设计》第6章的读书笔记

###1 前言

其实,在 上一篇博客:《JS高级程序设计》第6章读书笔记:创建对象(二)原型模式和组合模式,我们讨论了原型了模式,但是关于原型,我们还没讲完。

这一节,我们讨论原型的一些细节。

###2 原型与in操作符

在单独使用in操作符时,如果能够通过对象访问给定属性,无论是是通过原型还是实例,则会返回true

function Person() {}
Person.prototype.name = 'Nicholas';
Person.prototype.age = '29';
let p1 = new Person();
console.log('name' in p1); //true
p1.name = 'hhhha';
console.log('name' in p1); //true
delete p1.name1

从上述代码看出,可以无论是通过实例,还是原型访问属性name, 调用 name in p1 都返回true。

根据Object.hasOwnProperty()接口和in 操作符可以间接判断一个属性是否存在于原型。

//判断一个属性是否是原型属性
function hasPrototypeProperty(object, name) {
    return !object.hasOwnProperty(name) && (name in object);
}

function Person() {}
Person.prototype.name = 'achao';
Person.prototype.getName = function() {
    return this.name;
}
p1 = new Person();
console.log(hasPrototypeProperty(p1, 'name'));//true

for-in 循环

for-in循环时,返回的是能够通过对象访问的,可枚举的属性,不仅是实例属性,还是原型属性(包括屏蔽了原型中不可枚举的的实例,但是I8及其IE8-是例外,而这是违反规范的。)

//for-in 循环屏蔽原型属性的实例属性
var o = {
    toString: function() {
        return 'my object';
    }
}
for (var prop in o) {
    if (prop == 'toString') {
        console.log("found tostring");
    }
}

Object.keys()

Object.keys()获取对象上所有可枚举的实例属性或者原型属性


function Person() {}
Person.prototype.name = 'achao';
Person.prototype.getName = function() {
    return this.name;
}
p2 = new Person();
p2.name = 'yujie';

//Object.keys()获取实例对象上所有可枚举的实例属性或者原型的所有可枚举的原型属性,分别传入原型对象和实例对象
var keys = Object.keys(Person.prototype);
console.log(keys); // ['name','getName']
var p2keys = Object.keys(p2);
console.log(p2keys);//['name']

Object.getOwnPropertyName()

这个方法可以获取原型对象的所有属性,且无论是否可以枚举。传入参数为原型对象

var allkeys = Object.getOwnPropertyNames(Person.prototype);
console.log(allkeys);
//['constructor','name','getName']

###3 原型的动态性

重写原型会不能建立实例对象和新原型对象之间的联系,而且切断了构造函数与旧原型对象之间的联系。

看下面这段代码。

function Person() {}
var friend = new Person();
Person.prototype = {
    constructor: Person,
    name: 'Nicholas',
    age: 29,
    job: "Software Engineer",
    sayName: function() {
        console.log(this.name);
    }
}
friend.sayName(); //​​friend.sayName is not a function​​

下图清晰地描述上面代码重写原型后的结果:实例对象的[[prototype]]属性还是指向旧原型对象,不是新原型对象;新构造函数的prototype属性不再指向旧原型对象。

所以friend实例不能访问到新原型对象的方法。

这里写图片描述

###4 原生对象的原型

所有原生引用类型都是通过原型模式创建的。所有原生类型(Oject,Array,String等等)都原型对象上定义了方法。如Array.prototype.splice()

像自定义类型一样,原生类型的属性也可以被修改和增加。

例子可以看:这篇博文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值