工厂模式
解决了创建多个类似对象的问题,但没有解决对象的标识问题。
// 工厂模式
function creatPerson(name) {
let o = new Object();
o.name = name;
o.sayName = function () {
console.log(this.name)
}
return o
}
let person = creatPerson('job');
构造函数的模式
// 构造函数模式
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log(this.name)
}
}
let person1 = new Person('job', 12)
new操作符过程发生了什么
- 在内存中创建一个对象
- 这个对象内部的__ proto __特性,被赋值为构造函数的prototype属性
- 构造函数内部this被赋值为这个新对象(即this指向新对象)
- 执行构造函数内部代码,给新对象添加属性
- 如果构造函数返回非空对象,则返回该对象,否则返回刚刚创建的对象。
// ?new的时候发生了什么
function selfNew() {
let obj = Object.create({});
obj.__proto__ = Person.prototype;
let o = Person.call(obj);
return o ? obj : o;
}
new出来的实例构造器即construction属性均指向Person,用于标识对象类型。
优点:可以确保实例被标识为特定类型。
问题:方法会在每个实例上都创建一遍,可以将方法放置到函数外,或者使用原型模式解决。
原型模式
每个函数都会创建一个prototype属性,包含应该由特定引用类实例共享的属性和方法。这个对象就是通过构造函数创建对象的原型。
// 原型模式
function PresonProto() {
}
PresonProto.prototype.name = "person";
PresonProto.prototype.age = 239;
PresonProto.prototype.name = "person";
PresonProto.prototype.sayName = function () {
console.log(this.name)
};
function Test(){
}
console.log(typeof Test.prototype)//object
console.log(Test.prototype)
Object constructor: ƒ Test() __proto__: Object
使用 原型的好处就是,在他上面定义的属性和方法都可以被对象实例共享。
-
理解原型
- 创建一个函数,就会按特定规则为函数创建prototype属性(指向原型对象)
- 默认情况下所有原型对象会自动获得一个名为constructor属性,指回与之关联的构造函数。Person.prototype.constructor 指向 Person。换句话说二者互相引用
- 调用构造函数回创建一个新实例,这个实例内部[[prototype]]指针回被赋值为构造函数的原型对象,浏览器会暴露proto属性,通过这个属性可以访问对象的原型。
- 正常的原型链都会止于object原型对象
- object的原型对象是null
-
原型层级
- hasOwnPrototype
-
原型和in操作符
- 可以单独使用in操作符和for-in
-
属性枚举顺序
- object.keys()和for-in 是无序
- getOwnPropertyNames是升序的,Object.getOwnPropertySymbols()和 Object.assign() 的枚举顺序是确定性的。