销售网站设计,微信分销系统合法吗,为什么用php做网站,重庆奉节网站建设说明
接JavaScript — [学习笔记]观察者模式 理解对象 工厂模式 构造函数模式上一篇构造函数模式创建的实例,不同实例的同一个方法是不相等的,为了解决这个问题.出现了原型模式
1. 原型模式
具体做法是,不在构造函数中定义对象实例的信息,而是将这些…说明
接JavaScript — [学习笔记]观察者模式 理解对象 工厂模式 构造函数模式上一篇构造函数模式创建的实例,不同实例的同一个方法是不相等的,为了解决这个问题.出现了原型模式
1. 原型模式
具体做法是,不在构造函数中定义对象实例的信息,而是将这些信息直接添加到原型对象中
function Person(){}
Person.prototype.name Nicholas;
Person.prototype.age 29;
Person.prototype.job Software Engineer;
Person.prototype.sayName function () {alert(this.name);
};
var person1 new Person();
person1.sayName(); // Nicholasvar person2 new Person();
person2.sayName(); // Nicholasconsole.log(person1.sayName person2.sayName); // true1.1 理解原型对象
1.1.1 prototype属性和constructor属性
创建一个函数(Person),就会根据一组规则创建一个prototype属性(Person.prototype)prototype上面还要一个constructor属性(必带技能),它(Person.prototype.constructor)指向函数Personprototype属性上的所有属性和方法会被所有使用new操作符生产的实例(person1, person2)共享实例person1、person2通过new Person得到,会有一个[[Prototype]]的指针(在浏览器中通过__proto__访问),它指向Person.prototype
1.1.2 读取某个属性的顺序
读取属性的模拟函数如下:
// obj是某个对象, attr是该对象的属性
const getVal (obj, attr) {// 如果对象中存在该属性则返回if(obj[attr]) {return obj[attr]} else if (obj.constructor Object) {// 是Objectreturn undefined} else{// 不是Object,检查其constructor指向的函数if(obj.constructor[attr]){return obj.constructor[attr]} else {// constructor指向的函数中不存在,顺着 __proto__ 属性找下去.getVal(obj.__proto__, attr);}}
}说明:
所有通过function声明的函数,都继承自FunctionFunction继承自Object
1.1.3 说说
通过上面的原型找属性的顺序,可以知道:
当使用new Person生成实例(person1)的时候,person1会有一个指向Person.prototype的指针__proto__当访问person1的属性或方法的时候,先从实例开始寻找,若找到了则返回,否则会顺着__proto__向上寻找 1.2 区分一个属性是否来自原型
需要明白下面2点:
使用in操作符会返回所有对象上的属性或者方法使用hasOwnProperty可以确定一个属性是否来自实例对象
// 判断一个熟悉是否来自原型
const fromPrototype (obj, attr) {return !obj.hasOwnprototype (attr in obj);
}1.3 Object.defineProperty
Object.defineProperty: 可以给一个对象添加属性,并对属性进行描述使用如下:
Object.defineProperty(Person.prototype, constructor, {enumerable: false,value: Person
})1.3.1 数据属性和访问器属性
JS中的属性类型分为: 数据属性和访问器属性数据属性包括:
[[Configurabal]]: 是否能被delete删除[[Numerable]]: 是否能被for-in循环访问属性[[Writeble]]: 是否可以被修改[[Value]]: 属性的值
访问器属性: Configurable、Numerable、Get(读取时触发) 、Set(修改时触发)
1.3.2 Object.defineProperty的使用
在使用对象字面量对函数的原型进行赋值的时候,会丢失原本的constructor属性使用Object.defineProperty为它加上constructor属性
function Person () {}
Person.prototype {name: marron,age: 18
}
Object.defineProperty(Person.prototype, constructor, {numerable: false,value: Person
})constructor是不能被for-in循环访问到的在字面量中直接赋值,会被for-in循环访问到
1.4 原型的动态性
可以先创建实例后修改原型
function Person () {};
cosnt friend new Person();
Person.prototype.sayHi () { console.log(SayHi) };
friend.sayHi();将上述代码修改为下面:
- Person.prototype.sayHi () { console.log(SayHi) };Person.prototype {sayHi: function () {console.log(SayHi);}}此时在调用friend.sayHi会报错: Uncaught TypeError: p1.sayHi is not a function, 原因如下:
使用new操作符时: 建立了一个指针 proto, 它指向 Person.prototype(这个是默认建立的),假设在空间A中,即此时 person1 先从自己的空间中取数据,若没有则去 A中找当对Person.prototype进行字面量赋值时, 它改变的是Person.prototype指针的指向,在上面的一系列操作实际是在空间B中.当完成了Person.prototype的字面量赋值后,相当于给Person的原型对象新开辟了一个空间B.而此时person1的__proto__还是指向A.故访问不到B
注:重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系.