目标
- 理解对象
- 创建对象实例
- 理解Js中的继承
前言
在中了解到了两种最简单的创建对象的方式,本篇详细讨论Js中各种创建对象的方法。
创建对象
重点需要搞清楚构造函数模式、原型模式和组合使用两种模式的创建对象实例方法。(明白前两个其实大概就明白了如何组合使用)
1、工厂模式
工厂模式是一种广泛使用的设计模式, 创建对象的工厂模式,简单地理解就是将new Object()
创建对象的具体过程封装为一个函数
function CreatSomething(){ const o = new object(); o.propertyName1='value1'; o.propertyName2='value2'; ... o.functionName=function (){ console.log(this.propertyName1); }}复制代码
工厂模式存在的问题是,没有解决对象识别的问题(无法判断一个对象是由哪个函数实例化的),因此用的也不多,作为一个了解。
2、构造函数模式
2.1、普通构造函数模式
通过Js的一些内置对象可以创建对象实例,如Object
、Array
等,也可以自定义构造函数,如:
funtion Something(val,num){ this.propertyName1=val; this.propertyName2=num; ... this.functionName=function (){ console.log(this.propertyName1); }}const something1=new Something('val1',21);const something2=new Something('val2',20);复制代码
与工厂模式的区别在于:
- 可以不用显式地创建对象(原因是被
new
承包了)...=new Object()
- 将属性和方法赋给了
this
对象 - 可以不
return
新对象
所以相比工厂模式,使用构造函数创建对象实例更简洁,高效。
那么,构造函数是如何将属性和方法赋给实例对象的呢?
关键在于:new 操作符
- 以及
this
指针、作用域等相关知识点,参考。
2.2、new操作符
对于new
操作符,我觉得理解下其执行步骤,应该就清楚了
- (1) 创建一个新对象
- (2) 将构造函数的作用域赋给新对象(将
this
绑定到这个新创建的对象) - (3) 执行构造函数中的代码(将属性和方法添加到这个新对象)
- (4) 返回该对象
补充:模拟一个new操作符的实现(建议了解清楚原型之后再回过头来看)
function myNew(func){ const objNull={}; //新对象 if (func.prototype !== null){ obj.__proto__=func.prototype; } const obj=func.apply(res,Array.prototype.slice.call(arguments,1)); //绑定this if ((typeof obj === "object" || typeof obj === "function") && obj !==null){ return obj; } return objNull; }复制代码
在StackOverflow查阅new的时候看到一个评论戳中笑点...
2.3、思考:构造函数创建对象实例存在的问题?
简单来说,构造函数的问题在其对象的方法上。
3、原型模式
3.1、理解原型对象
我们创建的每一个函数都有一个prototype
指针,指向一个对象(即原型对象),包含由当前函数派生出的所有实例共享的属性和方法。
当调用构造函数创建实例后,实例内部将会包含一个[[prototype]]
指针(浏览器中的实现是__proto__
),指向其构造函数的原型对象prototype
所以简单总结下,
- 实例
.__proto__
=构造函数.prototype
- 另外ES5中封装了一个方法,MDN建议使用这种方式来操作
Object.getPrototypeOf(
实例)==
构造函数.prototype
function Person(){...}const someone=new Person();someone.__proto__===Person.prototype //trueObject.getPrototypeOf(someone)===Person.prototype //true复制代码
3.2、普通原型模式
function Person(){ }Person.prototype.property1=val1;Person.prototype.property2=val2;Person.prototype.funcName=function (){ console.log(this.property1)};const someone = new Person();someone.fucName() // 输出val1复制代码
3.3、内置对象的原型
Object Array Date RegExp FUnction 基本包装类型Boolean Number String单体内置对象Global Math复制代码
3.4、思考:原型模式创建对象实例存在的问题?
对象中值为引用类型的属性会被各实例共享,也就是说在原型模式下,改变一个实例对象的 引用类型属性值会影响到其他所有实例对象。
4、组合使用构造韩式和原型模式
更多创建对象实例的方式
动态原型模式
寄生构造函数模式
稳妥构造函数模式
小结
此处应该有个小结,不过还没想好该写些什么。
水平有限,不准确的地方,欢迎指正。
参考:
- 《JavaScript高级程序设计》
- 《你不知道的JavaScript》