JS创建对象几种不同方法详解


Posted in Javascript onMarch 01, 2016

本文介绍了几种js创建对象的方法,分享给大家供大家参考,具体内容如下

1、工厂模式

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

JS创建对象几种不同方法详解

2、构造函数模式

JS创建对象几种不同方法详解 

与工厂模式相比:
1、没有显式的创建对象
2、直接将属性和方法赋给了this对象
3、没有return语句
要创建person的实例,必须使用new操作符,以这种方式调用构造函数实际上会经历4个步骤:
1、创建一个新对象
2、将构造函数的作用域赋给新对象
3、执行构造函数中的代码
4、返回新对象
创建自定义的构造函数可以将它的实例标识为一种特定的类型。
构造函数的缺点:
每个方法都有在每个实例上重新创建一遍。person1和person2都有一个sayName()的方法,但两个方法不是同一个Function实例。不同实例上的同名函数是不相等的。
创建两个完成同样任务的Function实例没有必要,而且还有this对象在,不需要在执行代码前就把函数绑定在特定对象上,可以像下面这样。

JS创建对象几种不同方法详解 

把sayName属性设置成全局的sayName函数,这样,由于sayName包含的是一个指向函数的指针,因此person1和person2对象就共享了同一个函数。
但是,如果对象需要定义很多方法,那么就要定义很多全局函数,自定义的引用类型也没有封装可言了。为了解决上述问题,引入原型模式。

3、原型模式

理解原型对象
我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。prototype是通过调用构造函数而创建的那个对象实例的对象原型,使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。

JS创建对象几种不同方法详解 

首先,解析器会问实例person1是否有name属性,如果有,就返回。
如果没有,就继续去person1的原型中搜索name属性,如果有就返回。
如果没有,再继续向person1的原型的原型中搜索。

JS创建对象几种不同方法详解 

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中返回。

JS创建对象几种不同方法详解 

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

JS创建对象几种不同方法详解 

这导致了person1.constructor不再指向Person,而是指向了Object。如果constructor很重要,则需要特意将其设为适当的值,如:

JS创建对象几种不同方法详解 

但是这种方式会导致constructor属性变成可枚举。
如果想设置为不可枚举的(默认不可枚举),可以使用Object.defineProperty(Person.prototype, “constructor”, {
enumerable: false,
value: Person
});
原型的动态性
由于在原型中查找值的过程是一次搜索,因此我们对原型对象所做的任何修改都能够立即从实例上反映出来。
如果重写整个原型对象,情况就不一样了。调用构造函数时会为实例添加一个指向最初原型的[[prototype]]指针,而把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。实例中的指针仅指向原型,而不指向构造函数。

JS创建对象几种不同方法详解 

person.prototype指向的是原本的原型对象,而不会指向新的原型对象。
原型对象的问题
原型模式最大问题是由其共享的本性所导致的。
对于包含引用类型值的属性来说,问题较为突出

JS创建对象几种不同方法详解 

本意只想修改person1的friends,但是却导致person2的friends属性值也改变了。因此我们很少单独使用原型模式。

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

创建自定义类型的最常用的方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性,这样每个实例都有自己的一份实例属性的副本,又同时共享着对方法的引用,最大限度的节省了内存。
JS创建对象几种不同方法详解 

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

Javascript 相关文章推荐
一些常用的JS功能函数(2009-06-04更新)
Jun 04 Javascript
jquery 简单的进度条实现代码
Mar 11 Javascript
IE本地存储userdata的一个bug说明
Jul 01 Javascript
THREE.JS入门教程(6)创建自己的全景图实现步骤
Jan 25 Javascript
jQuery插件实现表格隔行换色且感应鼠标高亮行变色
Sep 22 Javascript
indexOf 和 lastIndexOf 使用示例介绍
Sep 02 Javascript
js组件SlotMachine实现图片切换效果制作抽奖系统
Apr 17 Javascript
JS iFrame加载慢怎么解决
May 13 Javascript
jQuery 3 中的新增功能汇总介绍
Jun 12 Javascript
微信小程序获取微信运动步数的实例代码
Jul 20 Javascript
vue 封装 Adminlte3组件的实现
Mar 18 Javascript
Vue实现Layui的集成方法步骤
Apr 10 Javascript
jQuery中通过ajax的get()函数读取页面的方法
Feb 29 #Javascript
基于JavaScript实现文字超出部分隐藏
Feb 29 #Javascript
基于JavaScript实现百叶窗动画效果不只单纯flas可以实现
Feb 29 #Javascript
ClearTimeout消除闪动实例代码
Feb 29 #Javascript
JavaScript实现点击按钮字体放大、缩小
Feb 29 #Javascript
jquery trigger函数执行两次的解决方法
Feb 29 #Javascript
理解js回收机制通俗易懂版
Feb 29 #Javascript
You might like
小偷PHP+Html+缓存
2006/12/20 PHP
创建配置文件 用PHP写出自己的BLOG系统 2
2010/04/12 PHP
php将会员数据导入到ucenter的代码
2010/07/18 PHP
php异常处理方法实例汇总
2015/06/24 PHP
PHP环形链表实现方法示例
2017/09/15 PHP
thinkphp5.0整合phpsocketio完整攻略(绕坑)
2018/10/12 PHP
解决laravel-admin 自己新建页面里 js 需要刷新一次的问题
2019/10/03 PHP
laravel框架邮箱认证实现方法详解
2019/11/22 PHP
如何使Chrome控制台支持多行js模式——意外发现
2013/06/13 Javascript
关于Jquery操作Cookie取值错误的解决方法
2013/08/26 Javascript
Bootstrap Chart组件使用教程
2016/04/28 Javascript
浅谈JavaScript 浏览器对象
2016/06/03 Javascript
Javascript 高性能之递归,迭代,查表法详解及实例
2017/01/08 Javascript
jQuery实现右侧抽屉式在线客服功能
2017/12/25 jQuery
jQuery实现标签子元素的添加和赋值方法
2018/02/24 jQuery
JS构造一个html文本内容成文件流形式发送到后台
2018/07/31 Javascript
vue计算属性computed、事件、监听器watch的使用讲解
2019/01/21 Javascript
详解微信小程序工程化探索之webpack实战
2020/04/20 Javascript
jQuery实现鼠标滑动切换图片
2020/05/27 jQuery
vue Treeselect下拉树只能选择第N级元素实现代码
2020/08/31 Javascript
WebStorm无法正确识别Vue3组合式API的解决方案
2021/02/18 Vue.js
python实现下载pop3邮件保存到本地
2018/06/19 Python
Python内置方法和属性应用:反射和单例(推荐)
2020/06/19 Python
Python实现快速大文件比较代码解析
2020/09/04 Python
纯CSS实现设置半个字符的样式
2014/07/03 HTML / CSS
美国社交购物市场:MassGenie
2019/02/18 全球购物
工商管理专业学生的自我评价
2013/10/01 职场文书
《雾凇》教学反思
2014/02/17 职场文书
请假条的格式
2014/04/11 职场文书
大学优秀班集体申报材料
2014/05/23 职场文书
小学生关于梦想的演讲稿
2014/08/22 职场文书
《我爱祖国》演讲稿1000字
2014/09/26 职场文书
go语言map与string的相互转换的实现
2021/04/07 Golang
Java使用httpRequest+Jsoup爬取红蓝球号码
2021/07/02 Java/Android
Python各协议下socket黏包问题原理
2022/04/12 Python
Java 异步任务计算FutureTask
2022/04/28 Java/Android