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 相关文章推荐
9个JavaScript评级/投票插件
Jan 18 Javascript
基于jquery实现控制经纬度显示地图与卫星
May 20 Javascript
JS获取select的value和text值的简单实例
Feb 26 Javascript
JS打印组合功能
Aug 04 Javascript
AngularJS 与百度地图的结合实例
Oct 20 Javascript
vue2.0 常用的 UI 库实例讲解
Dec 12 Javascript
angularjs实现table增加tr的方法
Feb 27 Javascript
解决npm管理员身份install时出现权限的问题
Mar 16 Javascript
基于Vue 2.0 监听文本框内容变化及ref的使用说明介绍
Aug 24 Javascript
vue基于element-ui的三级CheckBox复选框功能的实现代码
Oct 15 Javascript
详解@Vue/Cli 3 Invalid Host header 错误解决办法
Jan 02 Javascript
jQuery控制input只能输入数字和两位小数的方法
May 16 jQuery
详解如何在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
JAVA/JSP学习系列之二
2006/10/09 PHP
PHP5 安装方法
2006/10/09 PHP
php disk_free_space 返回目录可用空间
2010/05/10 PHP
利用phpexcel把excel导入数据库和数据库导出excel实现
2014/01/09 PHP
使两个iframe的高度与内容自适应,且相等
2006/11/20 Javascript
jquery 查找iframe父级页面元素的实现代码
2011/08/28 Javascript
javascript中的return和闭包函数浅析
2014/06/06 Javascript
jQuery实现购物车计算价格功能的方法
2015/03/25 Javascript
JavaScript控制按钮可用或不可用的方法
2015/04/03 Javascript
AngularJS之ionic 框架下实现 Localstorage本地存储
2017/04/22 Javascript
关于页面刷新vuex数据消失问题解决方案
2017/07/03 Javascript
Vue.js中组件中的slot实例详解
2017/07/17 Javascript
详解使用Typescript开发node.js项目(简单的环境配置)
2017/10/09 Javascript
解决layui 复选框等内置控件不显示的问题
2018/08/14 Javascript
js使用formData实现批量上传
2020/03/27 Javascript
jQuery-ui插件sortable实现自由拖动排序
2018/12/01 jQuery
JS获取今天是本月第几周、本月共几周、本月有多少天、是今年的第几周、是今年的第几天的示例代码
2018/12/05 Javascript
jQuery实现动态操作table行
2020/11/23 jQuery
python脚本监控docker容器
2016/04/27 Python
Python实现KNN邻近算法
2021/01/28 Python
Python基于opencv的图像压缩算法实例分析
2018/05/03 Python
用Q-learning算法实现自动走迷宫机器人的方法示例
2019/06/03 Python
python实现各种插值法(数值分析)
2019/07/30 Python
scikit-learn线性回归,多元回归,多项式回归的实现
2019/08/29 Python
日本7net购物网:书籍、漫画、杂志、DVD、游戏邮购
2017/02/17 全球购物
Otticanet澳大利亚:最顶尖的世界名牌眼镜, 能得到打折季的价格
2018/08/23 全球购物
如何安装ruby on rails
2014/02/09 面试题
茶叶店创业计划书范文
2014/01/19 职场文书
2014年五四青年节活动策划书
2014/04/22 职场文书
产品发布会策划方案
2014/05/12 职场文书
中华美德颂演讲稿
2014/05/20 职场文书
2014年消防工作总结
2014/11/21 职场文书
护士长2015年终工作总结
2015/04/24 职场文书
大国崛起日本观后感
2015/06/02 职场文书
MySQL5.7并行复制原理及实现
2021/06/03 MySQL
java中重写父类方法加不加@Override详解
2021/06/21 Java/Android