1、工厂模式

弊端:没有解决对象的识别问题,即怎么知道一个对象的类型。

2、构造函数模式



与工厂模式相比:

1、没有显式的创建对象

2、直接将属性和方法赋给了this对象

3、没有return语句

要创建person的实例,必须使用new操作符,以这样的方式调用构造函数实际上会经历4个步骤:

1、创建一个新对象

2、将构造函数的作用域赋给新对象

3、运行构造函数中的代码

4、返回新对象

创建自己定义的构造函数能够将它的实例标识为一种特定的类型。

构造函数的缺点:

每一个方法都有在每一个实例上又一次创建一遍。person1和person2都有一个sayName()的方法。但两个方法不是同一个Function实例。不同实例上的同名函数是不相等的。

创建两个完毕相同任务的Function实例没有必要,并且还有this对象在,不须要在运行代码前就把函数绑定在特定对象上,能够像以下这样。



把sayName属性设置成全局的sayName函数,这样,因为sayName包括的是一个指向函数的指针,因此person1和person2对象就共享了同一个函数。

可是,假设对象须要定义非常多方法,那么就要定义非常多全局函数,自己定义的引用类型也没有封装可言了。

为了解决上述问题,引入原型模式。

3、原型模式

理解原型对象

我们创建的每一个函数都有一个prototype属性,这个属性是一个指针。指向一个对象,而这个对象的用途是包括能够由特定类型的全部实例共享的属性和方法。prototype是通过调用构造函数而创建的那个对象实例的对象原型,使用原型对象的优点是能够让全部对象实例共享它所包括的属性和方法。



首先,解析器会问实例person1是否有name属性。假设有。就返回。

假设没有,就继续去person1的原型中搜索name属性。假设有就返回。

假设没有,再继续向person1的原型的原型中搜索。



isPrototypeOf()确定实例和原型对象之间的关联

console.log(Person.prototype.isPrototypeOf(person1)); //true

Object.getPrototypeOf()返回的是[[prototype]]的值

console.log(Object.getPrototypeOf(person1));

//Person {name: “Yvette”, age: 26, job: “engineer”} 返回的是Person的原型对象。

console.log(Object.getPrototypeOf(person1) === Person.prototype)//true

console.log(Object.getPrototypeOf(person1).name);//”Yvette”

hasOwnProperty()方法能够检測一个属性是存在于实例中。还是存在于原型中,仅仅有给定属性存在于实例中。才会返回true。



console.log(person1.hasOwnProperty(“name”));//false

原型与in操作符

有两种方式使用in操作符:单独使用和在for-in循环中使用。

单独使用时,in操作符会在通过对象能够訪问给定属性时返回true,不管该属性在于实例中还是原型中。

使用for in循环,返回的是全部能够通过对象訪问的、可枚举的属性,当中既包括实例中的属性。也包括存在于原型中的属性。假设实例中的属性屏蔽了原型中不可枚举的属性,那么也会返回。IE9之前的版本号实现上有一个Bug,屏蔽不可枚举属性的实例属性不会在for-in中返回。



在IE9之前的吧按本中没有log信息。虽然person实例中的toString()方法屏蔽了原型中的不可 枚举的toString();

原型简写



这导致了person1.constructor不再指向Person,而是指向了Object。

假设constructor非常重要,则须要特意将其设为适当的值,如:



可是这样的方式会导致constructor属性变成可枚举。

假设想设置为不可枚举的(默认不可枚举),能够使用Object.defineProperty(Person.prototype, “constructor”, {

enumerable: false,

value: Person

});

原型的动态性

因为在原型中查找值的过程是一次搜索。因此我们对原型对象所做的不论什么改动都能够马上从实例上反映出来。

假设重写整个原型对象,情况就不一样了。调用构造函数时会为实例加入一个指向最初原型的[[prototype]]指针,而把原型改动为另外一个对象就等于切断了构造函数与最初原型之间的联系。实例中的指针仅指向原型,而不指向构造函数。



person.prototype指向的是原本的原型对象,而不会指向新的原型对象。

原型对象的问题

原型模式最大问题是由其共享的本性所导致的。

对于包括引用类型值的属性来说,问题较为突出



本意仅仅想改动person1的friends,可是却导致person2的friends属性值也改变了。因此我们非常少单独使用原型模式。

4、组合使用构造模式和原型模式

创建自己定义类型的最经常使用的方式,就是组合使用构造函数模式与原型模式。

构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性,这样每一个实例都有自己的一份实例属性的副本,又同一时候共享着对方法的引用,最大限度的节省了内存。



除了以上几种方式以外,另外还有动态原型模式,寄生构造模式和稳妥构造模式,可是鉴于使用频率较低,不再赘述。

JS创建对象几种不同方法具体解释的更多相关文章

  1. javascript(js)创建对象的模式与继承的几种方式

    1.js创建对象的几种方式 工厂模式 为什么会产生工厂模式,原因是使用同一个接口创建很多对象,会产生大量的重复代码,为了解决这个问题,产生了工厂模式. function createPerson(na ...

  2. [js]js中4种无节操的预解释情况

    js中4种无节操的预解释情况 - 1. if语句即使条件不成立,条件里的表达式也会进行预解释. - 2. 匿名函数的预解释: 只对等号左边与解释 - 3. 自执行函数的预解释: 不进行预就解释, 执行 ...

  3. javascript中创建对象的几种不同方法

    javascript中创建对象的几种不同方法 方法一:最直白的方式:字面量模式创建 <script> var person={ name:"小明", age:20, s ...

  4. JS创建对象的方式有几种

    相信但凡作为一个前端工程师,都被面试到过这个面试题目,HR考察的就是对oop思想的理解. 作为一个从后端转过来的怂逼,oop一直是心中的永远的痛啊. 这几天一直在通读js高级程序设计,重复理解js创建 ...

  5. JS 创建对象(常见的几种方法)

    贴个代码先: function O(user,pwd){ //use constructor this.user=user; this.pwd=pwd; this.get=get; return th ...

  6. JS高级---三种创建对象的方式

    JS高级---三种创建对象的方式 字面量的方式 (实例对象) 调用系统的构造函数 自定义构造函数方式 //创建对象---->实例化一个对象,的同时对属性进行初始化 var per=new Per ...

  7. JS基础语法---创建对象---三种方式创建对象:调用系统的构造函数;自定义构造函数;字面量的方式

    创建对象三种方式: 调用系统的构造函数创建对象 自定义构造函数创建对象(结合第一种和需求通过工厂模式创建对象) 字面量的方式创建对象 第一种:调用系统的构造函数创建对象 //小苏举例子: //实例化对 ...

  8. JS创建对象篇

    JS创建对象篇 Object构造函数创建 var person = new Object(); person.name = "Tom"; person.age = 10; pers ...

  9. JS 创建对象总结

    狭义:new 构造函数. (注:在JS中创建对象只有一种方式,就是new 构造函数.其中字面量的方式是一种语法糖,本质仍然是new 构造函数) 广义:工厂模式(解决复杂度) 构造函数模式(解决复杂度, ...

随机推荐

  1. Spring中使用注解 @Scheduled 执行定时任务

    来自:http://blog.51cto.com/dwf07223/1557145 注解@Scheduled 可以作为一个触发源添加到一个方法中,例如,以下的方法将以一个固定延迟时间5秒钟调用一次执行 ...

  2. 在 shell中, 我們可用 $0, $1, $2, $3 ... 這樣的变量分別提取命令行中变量

    代码: script_name parameter1 parameter2 parameter3 ...我們很容易就能猜出 $0 就是代表 shell script 名称(路径)本身,而 $1 就是其 ...

  3. ZZULIoj 1913: 小火山的计算能力

    Description 别人说小火山的计算能力不行,小火山很生气,于是他想证明自己,现在有一个表达式,他想计算出来. Input 首先是一个t(1<=20)表示测试组数.然后一个表达式,表达式长 ...

  4. 00032_ArrayList集合的遍历

    1.通过集合遍历,得到集合中每个元素,这是集合中最常见的操作 2.集合的遍历与数组的遍历很像,都是通过索引的方式 public class ArrayListDemo02 { public stati ...

  5. C/C++的类型安全

    类型安全很大程度上可以等价于内存安全,类型安全的代码不会试图访问自己没被授权的内存区域.“类型安全”常被用来形容编程语言,其根据在于该门编程语言是否提供保障类型安全的机制:有的时候也用“类型安全”形容 ...

  6. 在使用Cocos2d-JS 开发过程中需要用到的单体设计模式

    JavaScript 单体模式的一种实现 T.getInstance = (function () { var instance = null; return function () { return ...

  7. SPOJ - ADALIST,双端队列入门模板!

    ADALIST - Ada and List 这道题时限6.5s,激动人心啊,好多人STL一顿乱写AC,哈哈,如果熟悉双端队列的话这道题其实是很水的. 题意:n个数的数列,然后接下来Q次操作,每次可以 ...

  8. [luoguP3608] [USACO17JAN]Balanced Photo平衡的照片(树状数组 + 离散化)

    传送门 树状数组裸题 #include <cstdio> #include <cstring> #include <iostream> #include <a ...

  9. 【扩展kmp+最小循环节】HDU 4333 Revolving Digits

    http://acm.hdu.edu.cn/showproblem.php?pid=4333 [题意] 给定一个数字<=10^100000,每次将该数的第一位放到放到最后一位,求所有组成的不同的 ...

  10. 【2018.10.27】CXM笔记

    一个数大约有 $O(\sqrt(n)/log^2(n))$ 个约数. 1. 一个棋盘,每个格子最开始都是白的.可以按一个格子,它马跳(日字跳)能到达的 $8$ 个格子反色(当前格不反色).问有多少种方 ...