fuziwang 2019-06-28
在创建对象的时候,使用对象字面量和 new Object() 构造函数的方式创建一个对象是最简单最方便的方式。但是凡是处于初级阶段的事物都会不可避免的存在一个问题,没有普适性,意思就是说我要为世界上(程序中)的所有使用到的对象都使用一遍 var xxx = {}
,对于'懒惰'的程序员来讲是不可以接受的。即便你能接受这种创建的方式,也无法保证将所有对象归类这一哲学问题。
由此,优秀的程序员们利用现有的规则,创造出了一种种优秀的解决方案 -- 这些优秀的解决方案统称为设计模式。
在 JavaScript 中,设计模式由初级到高级的区别是他们的副作用的大小。依次可以分为:
同时,使用设计模式也可以优雅的解决 JavaScript 在 ES6之前都是没有类的尴尬问题。
工厂模式,顾名思义就是创建对象的一个工厂,工厂可以创造一类具有相似结构和功能的对象。这个模式的诞生也<span style="color: red">基本</span>解决了:
先看下在这种设计模式下,应该如何组织我们的代码:
function createPerson(name, age) { var obj = new Object(); obj.name = name ; obj.age = age; obj.say = function() { console.log(this.name)} return obj; } var p1 = createPerson('ZhangSan', 12); p1.say() //ZhangSan
当然,处于初级阶段的 工厂模式, 一定有它处于初级阶段的道理:
优势:
缺点:
在 JavaScript 的开发中,经常会听说和使用的一个词语叫做构造函数,这里的构造函数就是出自构造函数模式这一种设计模式。在长时间的传承中,文化或者其他的名词都会变成一种泛称,所以人们常说的构造函数,有的时候指的是构造函数模式,有的时候指的是构造函数模式创造的对象中的构造函数方法(实例的 constructor )。
构造函数是用来创建特定的类型的对象的。比如Js原生提供的Object
, Array
。都是构造函数模式创建的原生构造函数。
惯例,看下在这种设计模式下,该如何组织代码:
function Person (name, age) { this.name = name; this.age = age; this.say = function() { console.log(this.age); } } var p1 = new Person('ZhangSan', 12); var p2 = new Person('LiSi', 22); p1.say() // 12 p2.say() // 22
使用构建函数模式和工厂模式创建对象的区别:
new Object()
的过程)new Person()
进行创建。使用构造函数创建对象经历了以下四个过程:
由构造函数创建的对象称为这个构造函数的<span style="color: red">实例</span>,在实例中会存在一个 constructor 属性,这个属性指向创造它的构造函数。(证明自己从哪里来)
p1.constructor == Person; // true p2.constructor == Person; // true
每一个实例都是可以被检测出来的,检测对象是否属于某一个类型,可以使用 instanceof XX
。
p1 instanceof Person // true p1 instanceof Object // true
知道了构造函数模式创建实例的过程和方法,下面介绍一些使用构造函数方法中,一些不为人知的秘密(高级知识点):
new
。但是也可以直接当做一个普通的函数使用。// Person 在上个 Demo var p3 = Person('Person3', 33); p3; // undefined; p3.say(); // undefined; Person('Person4', 44); window.say(); // 44;
undefined
。 call
把 this 指向其他对象。(不了解 call,可以先忽略。call 是改变 this 指针的方式之一)。了解了高级用法之后,细心的孩子已经发现了构造函数方法作为 Level 2的设计模式,一定有哪里不对。其实很简单,在构造函数创建的过程中,很好的解决了工厂模式创建对象不知道类型的问题(不知道自己从哪里来)。在构想上,实例的属性和方法应该都是唯一指向的,理想情况是都指向构造函数。但是差强人意的地方出现了:
this.name = name
p1.say === p2.say // false
this.say = function() {}
就是 this.say = new Function()
啊。这个时候,一个构造函数的补救措施出现了:
var Person = function(name, age) { this.name = name; this.age = age; this.say = sayFunc; } var sayFunc = function() { console.log(this.age) }
<u>俗话说的好,补救措施终究是补救措施</u>:
所以,构造函数的方法仍然是一个不完美的方法。但是在开发速度上,构造函数的设计模式还是有很大优势的。
而且当你需要你的方法在全局被使用的时候,构造函数模式是最适合的,这也是 Object, Array
原生构造函数出现的原因。
是一道经常出现在前端面试时的问题。如果只是简单的了解new关键字是实例化构造函数获取对象,是万万不能够的。更深入的层级发生了什么呢?同时面试官想从这道题里面考察什么呢?下面胡哥为各位小伙伴一一来解密。