javascript高级程序设计阅读收获(8.2.4)——原型模式

1. 理解原型prototype

function Person(){};
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Engineer";
Person.prototype.sayName = function(){
	console.log(this.name);
};
let person1 = new Person();
person1.sayName();//Nicholas
let person2 = new Person();
person2.sayName();//Nicholas
console.log(person1.sayName == person2.sayName);//true
  1. 我们要理解,构造函数(Person),原型对象(Person.prototype/person1[[Prototype]]),实例(person1/person2)他们之间的关系,这三者是三个不同的对象。
  2. 构造函数的prototype属性指向原型对象:Person.prototype = 原型对象
  3. 原型对象的constructor属性引用这个构造函数:Person.prototype.constructor = Person
  4. 实例的[[Prototype]](通过__proto__来访问)指向原型对象:person1.__propt__ = Person.prototype
  5. 正常的原型链都会终止于Object的原型对象,Object对象的原型的原型是null。
  6. instanceof用来检查实例的原型链中是否包含指定构造函数的原型。

2.关于原型的一些方法

function Person(){};
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Engineer";
Person.prototype.sayName = function(){
	console.log(this.name);
};

let person1 = new Person();
let person2 = new Person();
console.log(Person.prototype.isPrototypeOf(person1));//true
console.log(Person.prototype.isPrototypeOf(person2));//true
  1. 用原型对象调用isPrototype来检查实例__proto__是否指向这个原型对象。
function Person(){};
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Engineer";
Person.prototype.sayName = function(){
	console.log(this.name);
};

let person1 = new Person();
let person2 = new Person();
console.log(Object.getPrototypeOf(person1)== Person.prototype);//true
console.log(Object.getPrototypeOf(person1).name);//Nicholas
  1. Object.getPrototypeOf方法来获取实例的原型对象。也可以通过实例的__proto__属性
let biped = {
	numLegs:2
};
let person = {
	name: 'Matt'
};
Object.setPrototypeOf(person,biped);
console.log(person.name);//Matt
console.log(person.numLegs);//2
console.log(Object.getPrototypeOf(person) === biped);//true
  1. Object.setPrototypeOf方法可以向实例的私有属性[[Prototype]]写入一个新值,用来重写一个对象的原型继承关系。该方法会严重影响代码性能。
let biped = {
	numLegs: 2
};
let person = Object.create(biped);
person.name = 'Matt';

console.log(person.name);//Matt
console.log(person.numLegs);//2
console.log(Object.getPrototypeOf(person) === biped);//true
  1. 为避免使用Object.setPrototpeOf可能造成的性能下降,可以通过Oject.create来创建一个新对象,同时为其指定原型。

2.原型层级

function Person(){};
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Engineer";
Person.prototype.sayName = function(){
	console.log(this.name);
};


let person1 = new Person();
let person2 = new Person();

person1.name = "Greg";
console.log(person1.name);//Greg
console.log(person2.name);//Nicholas
delete person1.name;
console.log(person1.name);//Nicholas
  1. 通过对象访问属性时,会按照这个属性的名称开始搜索。
    (1)如果实例上发现了给定的名称,则返回该名称对应的值。
    (2)如果实例上没有找到这个属性,则搜索会沿着指针进入原型对象,然后在原型对象上找到属性后,再返回对应的值。
  2. 可以通过实例来读取原型对象上的值,但是不能通过实例来重写这些值。
  3. 可以给实例添加一个属性,这个属性就会遮蔽原型对象上的同名属性。
  4. 使用delete操作符删除实例上这个属性,才能取消这个遮蔽。
function Person(){};
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Engineer";
Person.prototype.sayName = function(){
	console.log(this.name);
};

let person1 = new Person();
let person2 = new Person();
console.log(person1.hasOwnProperty("name"));//false
person1.name = "Grey";
console.log(person1.hasOwnProperty("name"));//true
  1. hasOwnProperty这个方法用于判断元素来自于实例中还是原型中。
    (1)来自于实例中则返回true
    (2)来自于原型中则返回false
  2. Object.getOwnPropertyDescriptor方法只对实例属性有效。要取得原型属性的描述符,就必须直接在原型对象上调用Object.getOwnPropertyDescriptor。

3.原型和in操作符

function Person(){};
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Engineer";
Person.prototype.sayName = function(){
	console.log(this.name);
};
let person1 = new Person();
let person2 = new Person();
console.log("name" in person1);//true
person1.name = "Grey";
console.log("name" in person1);//true
  1. in操作符与hasOwnProperty方法不同,无论该属性是在实例上还是在原型上,该操作符都会返回true。
console.log(!Object.hasOwnProperty("name")&&("name" in person1))
  1. 可以用上面的方式来确定元素是否存在与于原型上
function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Engineer";
Person.prototype.sayName = function(){
	console.log(this.name);
};
let keys = Object.keys(Person.prototype);
console.log(keys);//["name", "age", "job", "sayName"]

let p1 = new Person();
p1.name = "Rob";
p1.age = 31;
let p1keys = Object.keys(p1);
console.log(p1keys);//["name", "age"]
  1. Object.keys方法接收一个对象作为参数,返回包含该对象所有可枚举属性名称的字符串数组。
function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Engineer";
Person.prototype.sayName = function(){
	console.log(this.name);
};
let keys = Object.getOwnPropertyNames(Person.prototype);
console.log(keys);//["constructor", "name", "age", "job", "sayName"]
  1. Object.getOwnPropertyNames接受一个对象作为参数,返回包含其所有实例属性的数组。
let k1 = Symbol('k1');
let k2 = Symbol('k2');
let o = {
	[k1]:'k1',
	[k2]:'k2',
	name:"aaaaa"
};
console.log(Object.getOwnPropertySymbols(o));
  1. Object.getOwnPropertyNames接收一个对象作为参数,返回包含其符号属性的数组。

4.属性枚举排序

let k1 = Symbol('k1');
let k2 = Symbol('k2');

let o = {
	1:1,
	first:'first',
	[k1]:'sym2',
	second:'second',
	0:0
};
o[k2]='sym2';
o[3] = 3;
o.thired = 'thired';
o[2] = 2;
console.log(Object.getOwnPropertyNames(o));//["0", "1", "2", "3", "first", "second", "thired"]
console.log(Object.getOwnPropertySymbols(o));//[Symbol(k1), Symbol(k2)]
  1. 在属性枚举中:
    (1)for-in循环和Object.keys的枚举顺序是不确定的,取决于JavaScript引擎,可能因浏览器而异。
    (2)Object.getOwnPropertyNamesObject.getOwnPropertySymbolsObject.assign他们的枚举顺序是确定性的。先以升序枚举数值键,然后以插入顺序枚举字符串和符号键
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木子 旭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值