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 相关文章推荐
encode脚本和normal脚本混用的问题与解决方法
Mar 08 Javascript
25个非常棒的jQuery滑块插件和教程小结
Sep 02 Javascript
ie与ff下的event事件使用介绍
Nov 25 Javascript
JavaScript初学者建议:不要去管浏览器兼容
Feb 04 Javascript
jQuery中append()方法用法实例
Jan 08 Javascript
js实现百度联盟中一款不错的图片切换效果完整实例
Mar 04 Javascript
jQuery选取所有复选框被选中的值并用Ajax异步提交数据的实例
Aug 04 jQuery
用js实现每隔一秒刷新时间的实例(含年月日时分秒)
Oct 25 Javascript
对于防止按钮重复点击的尝试详解
Apr 22 Javascript
在react中使用vue的状态管理的方法示例
May 02 Javascript
vue vant中picker组件的使用
Nov 03 Javascript
原生Js 实现的简单无缝滚动轮播图的示例代码
May 10 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
推荐几部必看的DC动画电影
2020/03/03 欧美动漫
php cli 方式 在crotab中运行解决
2010/02/08 PHP
基于xcache的配置与使用详解
2013/06/18 PHP
php阻止页面后退的方法分享
2014/02/17 PHP
两千行代码的PHP学习笔记汇总
2014/10/05 PHP
PHP实现的基于单向链表解决约瑟夫环问题示例
2017/09/30 PHP
laravel model 两表联查示例
2019/10/24 PHP
PHP正则表达式函数preg_replace用法实例分析
2020/06/04 PHP
jquery 关键字“拖曳搜索”之“拖曳”以及 图片“提示自适应放大”效果 的实现
2010/04/18 Javascript
使用js的replace()方法查找字符示例代码
2013/10/28 Javascript
JavaScript实现快速排序的方法
2015/07/31 Javascript
JavaScript+html5 canvas制作色彩斑斓的正方形效果
2016/01/27 Javascript
浅谈json取值(对象和数组)
2016/06/24 Javascript
js手动播放图片实现图片轮播效果
2016/09/17 Javascript
Node.js中路径处理模块path详解
2016/11/14 Javascript
angularjs定时任务的设置与清除示例
2017/06/02 Javascript
Vue Cli与BootStrap结合实现表格分页功能
2017/08/18 Javascript
Vue一个案例引发的递归组件的使用详解
2018/11/15 Javascript
手把手15分钟搭一个企业级脚手架
2019/09/16 Javascript
关于vue 项目中浏览器跨域的配置问题
2020/11/10 Javascript
[01:01:01]完美世界DOTA2联赛循环赛 GXR vs FTD BO2第一场 10.29
2020/10/29 DOTA
Python实现SSH远程登陆,并执行命令的方法(分享)
2017/05/08 Python
python实现向微信用户发送每日一句 python实现微信聊天机器人
2019/03/27 Python
Python从列表推导到zip()函数的5种技巧总结
2019/10/23 Python
python飞机大战pygame碰撞检测实现方法分析
2019/12/17 Python
python 浅谈serial与stm32通信的编码问题
2019/12/18 Python
Python3 shelve对象持久存储原理详解
2020/03/23 Python
欧洲有机婴儿食品最大的市场:Organic Baby Food(供美国和加拿大)
2018/03/28 全球购物
Carolina工作鞋官网:Carolina Footwear
2019/03/14 全球购物
劳动之星获奖感言
2014/02/01 职场文书
公务员转正考察材料
2014/02/07 职场文书
记账会计岗位职责
2014/06/16 职场文书
体育教育毕业生自荐信
2014/06/29 职场文书
服务员岗位职责范本
2015/04/09 职场文书
公司欠款证明
2015/06/24 职场文书
2019年新郎保证书3篇
2019/10/17 职场文书