JS创建对象的七种方法

1. 工厂模式

function createPerson(name, age) {
	var o = new Object();
	o.name = name;
	o.age = age;
	o.sayName = function() {
		alert(this.name);
	};
	return o;
}

var person1 = createPerson("王钱青",24);
console.log(person1.constructor); // Object() {[native code]}

问题: 实例化出来的对象类型无法确定,实例化出来的对象全是Object类型,未解决这一问题,引入构造函数模式

2. 构造函数模式

function Person(name,age) {
	this.name = name;
	this.age = age;
	this.sayName = function() {
		alert(this.name);
    };
}

var person1 = new Person("张三", 24);
var person2 = new Person("李四", 22);
console.log(person1.constructor); // Person构造函数
console.log(person2.constructor); // Person构造函数

使用new操作符,实例化对象的4个步骤

  • 开辟堆内存空间,创建新对象。
  • 将构造函数的作用域赋给新对象(this指向这个新对象)。
  • 执行构造函数中代码(为这个新对象添加属性)。
  • 返回新对象。
    可以使用instanceof检测对象类型
    alert(person1 instanceof Object); // true
    alert(person1 instanceof Person); // true
    问题:每实例化一个对象,就创建一个sayName方法,造成内存空间浪费,简单的解决思路,如下把方法声明在构造函数外部
function Person(name, age) {
	this.name = name;
	this.age = age;
	this.sayName = sayName;
}
function sayName() {
	alert(this.name);
}

这个办法虽然解决方法共享问题,但却体现不出面向对象思想的封装性。于是引入下面原型模式。

3. 原型模式

function Person() {}
Person.prototype.name = "王钱青";
Person.prototype.age = 24;
Person.prototype.sayName = function() {
	alert(this.name);
};
// 简单的原型语法
function Person() {}
Person.prototype = {
	constructor: Person, //这里必须指定constructor,因为对象字面量相当于创建了一个新的对象,覆盖掉原来的
	name: "王钱青",
	age: 24,
	sayName: function() {
		alert(this.name);
    }
};

问题: 无法传递参数,所有实例默认情况下共享相同的初始值。
最大问题是共享本身所导致的,共享对函数非常合适,基本值的属性也说得过去,对引用属性问题最大,如下

function Person() {}
Person.prototype = {
	name: "wqq",
	age: 24,
	friends: ["张三","李四"],
	sayName: function() {
		alert(this.name);
    }
};
var p1 = new Person();
var p2 = new Person();
p1.friends.push("凌云");
console.log(p1.friends); // ["张三", "李四", "凌云"]
console.log(p2.friends); // ["张三", "李四", "凌云"]

当我修改p1的friends属性时,由于数据共享,p2的friends属性也被改变,这种情况使我们不想看到的,于是引入组合构造函数和原型模式

4. 组合构造函数和原型模式

function Person(name, age) {
	this.name = name;
	this.age = age;
	this.friends = ["张三","李四"];
}
Person.prototype = {
	constructor: Person,
	sayName: function() {
		alert(this.name);
	}
};
var p1 = new Person();
var p2 = new Person();
p1.friends.push("凌云");
console.log(p1.friends); // ["张三", "李四", "凌云"]
console.log(p2.friends); // ["张三", "李四"]

这种方法是使用最广泛的,认同度最高的一种方法,也是默认的创建自定义类型的方法。又因为构造函数和原型分开,所以会使有oo语言经验的开发人员感到困惑,由此引入动态原型模式

5. 动态原型模式

function Person(name, age) {
	this.name = name;
	this.age = age;
	if (typeof this.sayName != "function") {
		Person.prototype.sayName = function () {
			alert(this.name);
		};
	}
}

if语句部分,只会在第一次实例化对象时运行。

6. 寄生构造函数模式

function  Person(name, age) {
	var o = new Object();
	o.name = name;
	o.age = age;
	o.sayName = function() {
		alert(this.name);
    };
    return o;
}

7. 稳妥构造函数模式

function Person(name, age) {
	var o = new Object();
	// 可以在这里定义私有变量和函数
	o.sayName = function () {
		alert(name);
	};
	return o;
}

实例化出来的是稳妥对象,除了调用sayName方法之外,没有其他办法访问数据成员,使得它非常适合在安全执行环境下使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值