6种对象创建的方式

学习目标:

1、工厂模式:可无数次调用的函数
2、构造函数模式:通过new操作符调用的函数
3、原型模式
4、

学习内容:

1、工厂模式
抽象了创建具体对象的过程,解决创建多个相似对象的问题,没有解决对象识别问题(怎样知道一个对象的类型)。考虑到在 ECMAScript 中无法创建类,因此用函数来封装创建对象。示例:

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");

可以无数次调用函数,每次都返回一个包含三个属性一个方法的对象。
2、构造函数模式
2.1构造函数的创建与调用
任何函数只要通过new操作符来调用,就可以作为构造函数(用于创建对象的函数)。
与工厂模式不同:没有显式地创建对象、直接将属性和方法赋给了 this 对象、没有 return 语句。
以这种方式定义的构造函数是定义在 Global 对象在浏览器中是 window 对象中的

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");
// 当作构造函数使用
var person = new Person("Nicholas", 29, "Software Engineer");
person.sayName(); //"Nicholas"
// 作为普通函数调用
Person("Greg", 27, "Doctor"); // 添加到 window
window.sayName(); //"Greg"
  • 使用new操作符,这种方式调用构造函数会经历以下4个步骤:
    (1) 创建一个新对象;
    (2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象)
    (3) 执行构造函数中的代码(为这个新对象添加属性);
    (4) 返回新对象。
  • 在前面例子的最后, person1 和 person2 分别保存着 Person 的一个不同的实例。这两个对象都有一个 constructor (构造函数)属性(该属性最初是用来标识对象的类型),该属性指向 Person .instanceof也可检测对象类型(所有对象均继承自Object):
alert(person1.constructor ==Person);//true
alert(person2.constructor==Person);//true
alert(person1 instanceof Object);//true
alert(person1 instanceof Person);//true

2.2、构造函数的问题
每个方法都要在每个实例上重新创建一遍,例如上面person1和person2的sayName() 的方法。不是同一个Function 的实例(ECMAScript 中的函数是对象)(每定义一个函数,也就是实例化了一个对象)(会导致不同的作用域链和标识符解析)

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

可改写为:

function Person(name, age, job){
	this.name = name;
	this.age = age;
	this.job = job;
	this.sayName = new Function("alert(this.name)"); // 与声明函数在逻辑上是等价的
}

创建两个完成同样任务的 Function 实例的确没有必要;况且有 this 对象在,根本不用在
执行代码前就把函数绑定到特定对象上面,因此应写为:

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

由于 sayName 包含的是一个指向函数的指针,因此 person1 和 person2 对象就共享了在全局作用域中定义的同一个 sayName() 函数
3、原型模式
每个函数都有一个 prototype (原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
3.1 理解原型对象
创建一个新函数:函数获得一个peototype属性,该属性指向函数的原型对象。
原型对象自动获得constructor(构造函数)属性,指向prototype属性所在函数的指针。
调用构造函数,创建一个新实例后:实例内部包含一个指针[[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

在这里插入图片描述alert(Person.prototype.isPrototypeOf(person1))//true
alert(Object.getPrototypeOf(person1).name)//“Nicholas”

读取属性时:首先搜索对象实例本身(Person1)>如果没有>搜索指针指向的原型属性(person)

person1.name="greg"
alert(person1.name)="greg"

判断是否来自实例:

alert(person1.hasOwnProperty("name"));//true 仅判断实例是否有

获取属性:

Object.getOwnPropertyDescriptor() //方法只能用于实例属性
//若要获取原型属性描述符,必须直接在原型对象上调用

in操作符:
in

"name" in person1//不论在原型还是实例中

for-in

for (var prop in person){
	if (prop == "name"){
		alert("Found toString");
	}
}

**Object.keys():**获取所有可枚举属性,接受参数为对象,返回数组

var keys = Object.keys(Person.prototype);

Object.getOwnPropertyNames():可枚举的不可枚举的都获得

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值