声明单个对象,不用说
let obj = {}
let object = new Object()
但声明多个对象就要一定技巧了
参考文章:
https://github.com/mqyqingfeng/Blog/issues/15
工厂模式
function createPerson(name) {
var o = new Object();
o.name = name;
o.getName = function () {
console.log(this.name);
};
return o;
}
var person1 = createPerson('kevin');
缺点:没法识别对象,每一个实例都指向
构造函数模式
function Person(name) {
this.name = name;
this.getName = function () {
console.log(this.name);
};
}
var person1 = new Person('kevin');
优点:实例可以被识别
// 不太推荐
alert(person1.constructor == Person)
// 推荐
alert(person1 instanceof Person)
缺点:每个方法都要在每个实例上重新创建一遍。
构造函数模式优化
function Person(name) {
this.name = name;
this.getName = getName;
}
function getName() {
console.log(this.name);
}
var person1 = new Person('kevin');
缺点:没有封装
原型模式
function Person(name) {
}
Person.prototype.name = 'keivn';
Person.prototype.getName = function () {
console.log(this.name);
};
var person1 = new Person();
优点:方法不会被重新创建
优化
function Person(name) {
}
Person.prototype = {
name: 'kevin',
getName: function () {
console.log(this.name);
}
};
var person1 = new Person();
优点:提高封装
缺点:重新了原型,缺少constructor属性
优化
function Person(name) {
}
Person.prototype = {
constructor: Person,
name: 'kevin',
getName: function () {
console.log(this.name);
}
};
var person1 = new Person();
优点:能通过constructor找到原型
缺点: 1. 所有的属性和方法都共享 2. 不能初始化参数
组合模式
function Person(name) {
this.name = name;
}
Person.prototype = {
constructor: Person,
getName: function () {
console.log(this.name);
}
};
var person1 = new Person();
优点:属性私有,函数共享
缺点:封装稍差
动态原型
function Person(name) {
this.name = name;
if (typeof this.getName != "function") {
Person.prototype.getName = function () {
console.log(this.name);
}
}
}
var person1 = new Person();
不能使用
Person.prototype = {
getName: function () {
console.log(this.name)
}
}
原因:
new操作符四个步骤:
- 创建一个新对象o
- o.prot = Object.prototype将新建的对象的_proto_属性指向构建函数的prototype
- Object.apply(o)
- 返回新对象
但是第四步有一个原则:如果构造函数Object有返回值,若返回值为基本类型(string, boolean, number, null, undefined, symbol),那么返回新对象。若返回值为对象类型,那么返回该对象。
所以根据这个规则改善了动态原型模式:
改进
function Person(name) {
this.name = name;
if (typeof this.getName != "function") {
Person.prototype = {
constructor: Person,
getName: function () {
console.log(this.name);
}
}
return new Person(name);
}
}
var person1 = new Person('kevin');
var person2 = new Person('daisy');
person1.getName(); // kevin
person2.getName(); // daisy
寄生构造函数模式
function Person(name) {
var o = new Object();
o.name = name;
o.getName = function () {
console.log(this.name);
};
return o;
}
var person1 = new Person('kevin');
console.log(person1 instanceof Person) // false
console.log(person1 instanceof Object) // true
稳妥构造函数模式
function person(name){
var o = new Object();
o.sayName = function(){
console.log(name);
};
return o;
}
var person1 = person('kevin');
person1.sayName(); // kevin
person1.name = "daisy";
person1.sayName(); // kevin
console.log(person1.name); // daisy
es5与es6定义对象的区别
1)class的构造函数必须使用new进行调用,普通构造函数不用new也可执行。
2)class不存在变量提升,es5中的function存在变量提升。
3)class内部定义的方法不可枚举,es5在prototype上定义的方法可以枚举。