JavaScript创建对象的几种方式

创建对象的几种方式

工厂模式

function createPerson(name, age, job){
	var o = new Object();
	o.name = name;
	o.age = age;
	o.job = job;
	o.sayName = function(){
		alert(this.name);
	};
	return o;
}
var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");

创建的对象都是object类型

构造函数模式

function Person(name, age, job){
	this.name = name;
	this.age = age;
	this.job = job;
	this.sayName = function(){
		alert(this.name);
	};
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

与工厂模式相比:

  • 没有显示的创建对象
  • 直接将属性和方法赋给this对象
  • 没有return语句
  • 创建实例需要用new

如果不使用new创建实例,构造函数就是一个普通的函数,this指向全局

Person("Greg", 27, "Doctor"); // 添加到window
window.sayName(); //"Greg"

可以使用call或apply在另一个对象的作用域调用

var o = new Object();
Person.call(o, "Kristen", 25, "Nurse");
o.sayName(); //"Kristen"

构造函数的问题:
构造函数中的方法,在每个实例中都会重新创建一遍
做同一件事情的方法被创建多次,是没有必要的。

alert(person1.sayName == person2.sayName); //false

可以将方法定义到构造函数的外部

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

如果有多个方法还得创建多个全局的函数?

原型模式

每个函数都有一个prototype(原型)属性(一个指针,指向一个对象),这个对象
包含所有实例共享的属性和方法。

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(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true
原型对象

创建一个新的函数,就会为该函数生成一个prototype属性,这个属性指向函数的原型对象。
原型对象会自动获取一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针。
这里写图片描述

从图中可以看到三种关系:
person1,person2:实例
Person: 构造函数
Person Prototype: 原型对象

实例与构造函数:
虽然实例是通过new 构造函数创建,但实例和构造函数之间没有关系。

实例与原型对象:
每个实例中包含一个[[Prototype]]的属性,指向原型对象,但却无法直接访问[[Prototype]]。
可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系。
Object.getPrototypeOf(),这个方法返回可以[[Prototype]]的值。

alert(Person.prototype.isPrototypeOf(person1)); //true
alert(Object.getPrototypeOf(person1) == Person.prototype); //true
alert(Object.getPrototypeOf(person1).name); //"Nicholas"

构造函数与原型对象:
构造函数的prototype指向原型对象,原型对象的constructor 又指回了构造函数。

hasOwnProperty() 和 in

hasOwnProperty()

hasOwnProperty()可以检测一个属性是存在实例中,还是存在原型中,
在实例中返回true,在原型中返回false。

in

in 操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。

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();
var person2 = new Person();
alert(person1.hasOwnProperty("name")); //false
alert("name" in person1); //true
person1.name = "Greg";
alert(person1.name); //"Greg" ——来自实例
alert(person1.hasOwnProperty("name")); //true
alert("name" in person1); //true
alert(person2.name); //"Nicholas" ——来自原型
alert(person2.hasOwnProperty("name")); //false
alert("name" in person2); //true
delete person1.name;
alert(person1.name); //"Nicholas" ——来自原型
alert(person1.hasOwnProperty("name")); //false
alert("name" in person1); //true

组合使用构造函数模式和原型模式

构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。
每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用。

function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
	constructor : Person,
	sayName : function(){
		alert(this.name);
	}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值