JavaScript创建对象的常用方式总结


Posted in Javascript onAugust 10, 2018

本文实例讲述了JavaScript创建对象的常用方式。分享给大家供大家参考,具体如下:

JS中没有类的概念,那么怎么创建对象呢?下面一一来细说!

传统的创建对象的方式:

1、创建Object的实例

var person = new Object();
person.name = "Alice";
person.age = 12;
person.showName = function() {
 alert(this.name);
};

2、对象字面量形式创建单个对象

var person = {
 name : "Alice";
 age : 12;
 showName : function() {
  alert(person.name);
 }
};

创建对象的五种设计模式

1、工厂模式

虽然Object构造函数和对象字面量都可以用来创建单个对象,但这个方式有个明显的缺点:使用同一个接口创建很多对象,会产生大量重复的代码。为了解决这个问题,开始使用工厂模式。

function createPerson(name, age) {
 var obj = new Object();
 obj.name = name;
 obj.age = age;
 obj.showName = function() {
  alert(this.name);
 };
 return obj;
}
var person1 = createPerson("Alice", 23);
var person2 = createPerson("Bruce", 22);

2、构造函数模式

工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即不知道对象的类型),于是,又出现了构造函数模式,自定义的构造函数意味着将来可以把它的实例识别为一种特定的类型。这是构造函数模式胜过工厂模式的地方。

function Person(name, age) {
 this.name = name;
 this.age = age;
 this.showName = function() {
  alert(this.name);
 };
}
var person1 = new Person("Alice", 23);
var person2 = new Person("Bruce", 22);

构造函数模式与工厂模式的不同之处在于:

1)没有显式地创建对象;

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

3)没有return语句

构造函数的问题:每个方法都要在每个实例上重新创建一遍。由于JavaScript中的函数是对象,每定义一个函数,就是实例化了一个Funtion对象,因此,使用构造函数创建的每个实例都有一个名为showName()的方法,但这些方法不是同一个Function的实例。不同实例上的同名函数是不相等的,因此person1.showName == person2.showName返回false。

可以通过把函数定义转移到构造函数外部来解决这个问题,如下:

function Person(name,age,job) {
 this.name = name;
 this.age = age;
 this.showName = showName;
}
function showName(){
 alert(this.name);
}
var person1 = new Person("Alice", 23);
var person2 = new Person("Bruce", 22);

这样虽然解决了方法多次创建问题,但又出现了新的问题:

(1)在全局作用域中定义的函数实际上只能被某个对象调用,这让全局作用域名不副实。

(2)如果对象需要定义很多方法,那么就需要定义很多个全局函数,那么就毫无封装性可言了。

这些问题可以通过使用原型模式来解决。

3、原型模式

每个函数都以一个原型prototype属性,是一个指针,指向一个对象。

使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象实例的信息,而是可以直接将这些信息添加到原型对象中。

function Person() {
}
Person.prototype.name = name;
Person.prototype.age = age;
Person.prototype.showName = function(){
 alert(this.name);
};
var person1 = new Person();
var person2 = new Person();

使用原型模式创建的新对象具有相同的属性和方法。与构造函数模式不同的是,新对象的这些属性和方法是由所有对象所共享的。这会导致所有实例默认有一样的属性值,因此person1.showName == person2.showName返回true。

读取某个对象的某个属性的搜索方法:

1)首先在实例中搜索,若找到指定属性,则返回该属性的值。

2)否则继续搜索指针指向的原型对象。

使用delete 实例名.属性名可以删除实例的某一属性。

使用hasOwnProperty()方法可以判断属性是存在于实例中,还是存在于原型中。只有给定属性存在于实例中,才会返回true。

in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。

同时使用hasOwnProperty()方法和in操作符,能够确定属性到底是存在于对象中,还是存在于原型中。

function Person () {
}
Person.prototype.name = "Alice";
Person.prototype.age = "22";
Person.prototype.showName = function(){
 alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
person1.name = "Bruce";
alert(person1.name);//Bruce
alert(person1.hasOwnProperty("name"));//true
alert("name" in person1);//true
alert(person2.name);//Alice
delete person1.name;
alert(person1.hasOwnProperty("name"));//false
alert("name" in person1);//true
alert(person1.name);//Alice

原型模式更简单的语法:以一个包含所有属性和方法的对象字面量来创建原型对象。

function Person () {
}
Person.prototype = {
  name:"Alice",
  age : "22",
  showName: function(){
   alert(this.name);
  }
};

用对象字面量来创建原型对象的结果相同,只是constructor属性不再指向Person。这是由于这样已经完全重写了默认的prototype对象,因此constructor属性也就变成了新对象的constructor属性,指向Object构造函数但不指向Person函数。此时,instanceof操作符还能返回正确的结果但通过constructor已经无法确定对象的类型了。

var person = new Person();
alert(person instanceof Object);//true
alert(person instanceof Person);//true
alert(person.constructor == Object);//true
alert(person.constructor == Person);//false

如果constuctor的值很重要,可以特意将其设置回适当的值。

function Person () {
}
Person.prototype = {
 constructor:Person,
  name:"Alice",
  age : "22",
  showName: function(){
   alert(this.name);
  }
};

重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系,对象实例引用的仍然是最初的原型。

function Person () {
}
var person = new Person();
Person.prototype = {
 constructor:Person,
 name:"Alice",
 age : "22",
 showName: function(){
  alert(this.name);
 }
};
person.showName();//报错:person.showName is not a function

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

原型对象的问题:最大问题是由于共享属性导致的。原型中所有属性是被实例共享的,这对于函数很合适,对那些包含基本值的属性也还说得过去,因为可以通过在实例上添加同名属性,隐藏原型中的对应属性。然而,对于包含引用值的属性来说,问题就比较突出了,修改某个实例的引用类型的属性也会通过原型影响到其它实例的该属性。

创建自定义类型的最常见方法是组合使用构造函数模式和原型模式,构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。

function Person(name, age) {
 this.name = name;
 this.age = age;
 this.friends = ["Bruce", "Cindy"];
}
Person.prototype = {
 constructor : Person,
 showName : function(){
  alert(this.name);
 }
};
var person1 = new Person("Alice",23);
var person2 = new Person("David",22);
person1.friends.push("Vincy");//包含引用值的属性friends
alert(person1.friends);//"Bruce", "Cindy","Vincy"
alert(person2.friends);//"Bruce","Cindy"
alert(person1.friends == person2.friends);//false
alert(person1.showName == person2.showName);//true

5、动态原型模式

动态原型模式把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型,又保持了同时使用构造函数和原型的优点。

可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。

如:只在showName()方法不存在的情况下,才会将它添加到原型中,这段代码只会在初次调用构造函数时才会执行。

function Person(name,age) {
 this.name=name;
 this.age=age;
 if(typeof this.showName!="function"){
  Person.prototype.showName=function(){
   alert(this.name);
  }
 }
}
alert(person1.hasOwnProperty("name"));//true

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
ExtJs使用总结(非常详细)
Mar 22 Javascript
js 操作select和option常用代码整理
Dec 13 Javascript
JavaScript处理解析JSON数据过程详解
Sep 11 Javascript
JavaScript动态创建form表单并提交的实现方法
Dec 10 Javascript
悬浮广告方法日常收集整理
Mar 18 Javascript
详解JSON1:使用TSQL查询数据和更新JSON数据
Nov 21 Javascript
JS实现小球的弹性碰撞效果
Nov 11 Javascript
利用jquery如何从json中读取数据追加到html中
Dec 01 jQuery
JS常见DOM节点操作示例【创建 ,插入,删除,复制,查找】
May 14 Javascript
vue js秒转天数小时分钟秒的实例代码
Aug 08 Javascript
使用Vue调取接口,并渲染数据的示例代码
Oct 28 Javascript
JavaScript中的相等操作符使用详解
Dec 21 Javascript
详解如何在nuxt中添加proxyTable代理
Aug 10 #Javascript
解决bootstrap中下拉菜单点击后不关闭的问题
Aug 10 #Javascript
快速解决bootstrap下拉菜单无法隐藏的问题
Aug 10 #Javascript
详解Vue+axios+Node+express实现文件上传(用户头像上传)
Aug 10 #Javascript
快速解决select2在bootstrap模态框中下拉框隐藏的问题
Aug 10 #Javascript
Bootstrap模态对话框中显示动态内容的方法
Aug 10 #Javascript
解决bootstrap-select 动态加载数据不显示的问题
Aug 10 #Javascript
You might like
PHP 实现代码复用的一个方法 traits新特性
2015/02/22 PHP
火狐textarea输入法的bug的触发及解决
2013/07/24 Javascript
jquery 新建的元素事件绑定问题解决方案
2014/06/12 Javascript
中文输入法不触发onkeyup事件的解决办法
2014/07/09 Javascript
Js中使用hasOwnProperty方法检索ajax响应对象的例子
2014/12/08 Javascript
JavaScript中的继承方式详解
2015/02/11 Javascript
javascript与css3动画结合使用小结
2015/03/11 Javascript
ES6下React组件的写法示例代码
2017/05/04 Javascript
VUE2.0中Jsonp的使用方法
2018/05/22 Javascript
Vue项目总结之webpack常规打包优化方案
2019/06/06 Javascript
实例分析JS中的相等性判断===、 ==和Object.is()
2019/11/17 Javascript
JS函数本身的作用域实例分析
2020/03/16 Javascript
如何区分vue中的v-show 与 v-if
2020/09/08 Javascript
vue 通过base64实现图片下载功能
2020/12/19 Vue.js
[04:36]DOTA2国际邀请赛 ti3精彩集锦
2013/08/19 DOTA
Python如何为图片添加水印
2016/11/25 Python
python创建文件备份的脚本
2018/09/11 Python
详解Python数据可视化编程 - 词云生成并保存(jieba+WordCloud)
2019/03/26 Python
python里dict变成list实例方法
2019/06/26 Python
详解python中的index函数用法
2019/08/06 Python
python爬虫开发之PyQuery模块详细使用方法与实例全解
2020/03/09 Python
推荐10个CSS3 制作的创意下拉菜单效果
2014/02/11 HTML / CSS
Marriott中国:万豪国际酒店查询预订
2016/09/02 全球购物
Cocopanda波兰:购买化妆品、护肤品、护发和香水
2020/05/25 全球购物
如何整合JQuery和Prototype
2014/01/31 面试题
个人实用简单的自我评价
2013/10/19 职场文书
大学生党课思想汇报
2013/12/29 职场文书
个人委托书怎么写
2014/04/04 职场文书
《悯农》教学反思
2014/04/28 职场文书
计算机网络及管理学专业求职信
2014/06/05 职场文书
解除劳动合同证明书模板
2014/11/20 职场文书
工作检讨书范文
2015/01/23 职场文书
2015年青年志愿者协会工作总结
2015/04/27 职场文书
2015年依法行政工作总结
2015/04/29 职场文书
2015年小学生暑假总结
2015/07/13 职场文书
初中数学课堂教学反思
2016/02/17 职场文书