1.通过对象字面量创建
var a = {}; //最简单最直接的方法,是第二种的简写方式
2.通过object构造函数创建
var a = new Object(); // 这行代码创建了Object引用类型的一个新实例,然后把实例保存在变量a中。
a.name = 'pingfan';
console.log(a); // 此时打印出来的是{name: 'pingfan'}
3.通过Object.create(__proto__, propertiesObject)创建
var a = Object.create(null); // 新创建出来的对象的原型指向null,也就是没有原型
console.log(a); // {}
__proto__ 是必填参数,就是新创建出来的对象的原型。
propertiesObject是可选参数,作用就是给新对象添加新属性以及描述器。
4.通过工厂模式创建
实际上是把创建对象的方式放在了一个函数里面,然后通过这个函数返回出一个对象。代码如下:
function creatObject(name) {
var a = new Object();
a.name = name;
a.sayName=function(){
alert(this.name);
};
return a;
}
var b = creatObject('pingfan');
console.log(b instanceof creatObject); // false 判断a的类型
// 用一个变量去接收函数返回的对象,var b = {name: 'pingfan', sayName:function(){ alert(this.name);}}
b.sayName(); // 调用b对象的sayName方法。
我们可以把creatObject函数看作是一个工厂在制造商品,而return出来的就是商品(对象),而这个b就是买商品的人,当我们买了一件商品的时候我们就可以去使用这件商品了
优点:可以重复调用creatObject函数,解决了创建多个相似对象的问题。
缺点:虽然它能创建多个相似的对象,但是不能识别这个对象属于哪个类型。
5.使用构造函数创建对象(Constructor)
对比工厂模式,它是工厂模式的进化版,因为它少了创建对象的步骤(实际上创建了,隐藏了),也没有return语句,代码如下:
function CreatObject(name) { // 首字母要大写,标明这是一个构造函数
this.name = name;
this.sayName = function() {
console.log(this.name);
};
}
var a = new CreatObject('pingfan'); // 使用new实例化构造函数
console.log(a) // CreatObject {name: "pingfan", sayName: ƒ} f代表的函数 CreatObject代表的是对象类型
console.log(a instanceof Object); // true 解决了工厂模式不能判断类型的问题
console.log(a instanceof CreatObject); // true
console.log(a.constructor == CreatObject); //true
优点:
可以重复new实例化构造函数,解决了工厂模式不能判断类型的问题
可以将构造函数的实例标识为某种特定的类型
采用new操作符调用构造函数
函数中隐式地创建对象
将属性和方法复制给了this对象
没有return语句
缺点:
实例对象都可以继承构造器函数中的属性和方法。但是,同一个对象实例之间,无法共享属性
构造函数中的每个方法都要在实例上重新创建一遍,封装性不好,原因如下:
var b = new CreatObject('xiaoran');
console.log(a.name); // pingfan
console.log(b.name); // xiaoran
console.log(a.sayName === b.sayName ); //false !!!!注意这里
由上可见a.sayName !== b.sayName,也就意味着每一次实例都要创建一遍,怎么办呢,继续优化呗。
6.使用原型模式(propotype)
因为构造函数创建对象也有缺点怎么办呢?这时候原型就蹦了出来,解决了构造函数的缺点。每个数据类型都是对象(undefined和null除外),而每个对象都是继承自一个原型对象,只有null除外,它没有自己的原型对象,最终的Object的原型为null,涉及到原型链知识点。代码如下:
function CreatObject() { // 首字母要大写,标明这是一个构造函数
}
CreatObject.prototype.name = 'pingfan';
CreatObject.prototype.sayName = function() {
alert(this.name);
};
var a = new CreatObject(); // 使用new实例化构造函数
var b = new CreatObject();
console.log(a.name); // a pingfan
console.log(b.name); // b pingfan
console.log(b.propotype.constructor); // CreatObject()
console.log(a.sayName === b.sayName); // true a和b都可以公用sayName方法
propotype是构造函数CreatObject的属性,而consructor则是构造函数的prototype的属性它所指向的是CreatObject构造函数
重写CreatObject.prototype对象会造成propotype.constructor属性不会指向CreatObject构造函数,实例对象拥有一个[[prototype]]指针,指向的是最初的原型对象,如果重写了原型对象,就相当于切断了构造函数和最初原型对象之间的联系
function CreatObject() { // 首字母要大写,标明这是一个构造函数
}
CreatObject.prototype = {
name: 'pingfan',
love: ['lol','98k'],
sayName: function() {
alert(this.name);
}
}
var a = new CreatObject(); // 使用new实例化构造函数
var b = new CreatObject();
a.love.push('you')
console.log(a.love); // a lol,98k,you
console.log(b.love); // b lol,98k,you
console.log(a.sayName === b.sayName); // true a和b都可以公用sayName方法
console.log(b.propotype.constructor); // undefined
优点:
方法不会重新创建。共享原型对象上的方法
缺点:
不能初始化参数。共享原型对象上的属性(比如属性的值是一个数组,当使用push方法添加元素的时候原数组被改变了)
7.组合模式
构造函数模式与原型模式的一起来,代码如下:
function CreatObject(name) {
this.name = name;
}
CreatObject.prototype = {
constructor: CreatObject,
getName: function () {
console.log(this.name);
}
};
var a = new CreatObject('pingfan');
var b = new CreatObject('xiaoran');
console.log(a); // CreatObject {name: "pingfan"}
a.getName(); // pingfan
b.getName(); // xiaoran
console.log(a.getName === b.getName); // true
优点:
以上问题都解决,该公用的公用,私用的私用
缺点:
封装性不是很好,
8.寄生构造函数模式
写法跟工厂模式和构造函数模式很像,构造函数的头,工厂模式的身体,构造函数的实例,推荐特殊情况下使用
function Person(name) {
var o = new Object();
o.name = name;
o.getName = function () {
console.log(this.name);
};
return o;
}
var person1 = new Person('pingfan');
console.log(person1 instanceof Person) // false
console.log(person1 instanceof Object) // true
9.稳妥构造函数模式
没有公共属性,而且其方法也不引用 this 的对象。新创建的实例方法不引用 this,也不使用 new 操作符调用构造函数
function person(name){
var o = new Object();
o.getName = function(){
console.log(name);
};
return o;
}
var person1 = person('kevin');
person1.getName(); // kevin
person1.name = "daisy";
person1.getName(); // kevin
console.log(person1.name); // daisy
--------------------------------------------------------------------------------------(完)-------------------------------------------------------------------------