关于JavaScript中的创建对象的学习总结
一、最简单的对象创建方法
在JavaScript中,直接使用Object构造函数或对象字面量都可以很轻易地创建单个对象,缺点是:创建具有同一个接口(标准的OO中的接口概念)的多个对象时,会有大量重复代码。为解决这个问题,引出了工厂模式。
二、工厂模式
工厂模式是GoF的23中设计模式中比较简单的模式,简单总结就是定义一个用于创建对象的接口,让子类决定具体实例化那一个类。具体到JavaScript中,因为根本就没有标准OO里面类的概念,开发人员发明了一种函数,用函数来封装以特定接口来创建对象的细节。
function createPerson(name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function() { alert(this.name); }; return o; } var person1 = createPerson("Haha", 34, "Doctor"); var person2 = createPerson("Hehe", 23, "worker");
使用工厂模式创建对象解决了代码重复的问题,却没有解决对象识别的问题:所有由createPerson函数创建的对象都是Object构造函数的实例。为了解决这个问题,引入了构造函数模式。
三、构造函数模式
通过创建自定义的构造函数,从而定义自定义对象类型的属性和方法。
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function() { alert(this.name); }; } var person1 = new Person("Haha", 34, "Doctor"); var person2 = new Person("Hehe", 23, "Worker");
此处,我们必须使用new操作符来调用构造函数Person()。这样就会有以下四个步骤:
1)创建一个新对象;
2)将新对象赋给构造函数的作用域(因此this就指向了这个新对象);
3)执行构造函数中的代码(为这个新对象添加属性);
4)返回新对象(没有明确return其他对象,默认返回新对象);
现在,person1和person2不仅仅都是Object构造函数的实例,而且都是Person构造函数的实例。构造函数模式的缺点是:每个构造函数中定义的方法在其生成的每个实例上都重新创建一遍,如果生成的实例比较多或者每个方法都比较大,这种模式会非常消耗资源。有一种变通方法如下:
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName() { alert(this.name); } var person1 = new Person("Haha", 34, "Doctor"); var person2 = new Person("Hehe", 23, "Worker");
通过把方法转移到构造函数外部,对象person1和person2实现了共享函数sayName()。带来的问题是sayName()函数处在全局作用域中,从而失去封装性问题和大量类似函数的数量膨胀问题。为此,我们想到了原型模式。
四、原型模式
我们创建的每个函数都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型(指向这个对象的函数)的所有实例共享的属性和方法。注意:这个对象是在创建函数的同时,就已经自动被创建了,而且通过函数的prototype属性和对象的constructor属性进行了相互指向。在对函数调用了new操作符之后,所有生成的实例把函数的prototype属性指向的对象作为自己的原型对象。
function Person() { } Person.prototype.name = "Haha"; Person.prototype.age = 34; Person.prototype.job = "Doctor"; Person.prototype.sayName = function() { alert(this.name); }; var person1 = new Person(); var person2 = new Person(); person1.sayName === person2.sayName;
各个对象之间的关系:
注意一:实例对象和构造函数没有直接的关联,它们只是在生成时,把自己的内部属性[[Prototype]]指向了Person Prototype对象,而和Person构造函数之间并没有之间联系起来。造成的影响是:当实例生成后去改变Person构造函数的prototype属性,使之重新指向一个对象的话,实例的[[Prototype]]属性不会跟随变化。
注意二:原型对象带来的对象属性的读和写的不对等性。
注意三:原型的动态性,本质是实例与原型之间的松散连接关系。
原型模式的问题是:1、没有了构造函数传递初始化参数这一环节;2、引用类型值的共享带来的问题。
五、组合使用构造函数模式与原型模式
因为构造函数模式和原型模式的优缺点互补性,创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.friends = ["shelBy", "court"]; } Person.prototype = { constructor : Person, sayName : function () { alert(this.name); } } var person1 = new Person("Haha", 34, "Doctor"); var person2 = new Person("Hehe", 23, "Worker");
到了这一步,JavaScript中创建对象的方法应该学习的差不多了,但是,总会有一些特殊需求。
六、动态原型模式
如果你对上面第五种方法中的组合模式感到困惑或者不爽,那么你可以试试这个动态原型模式。它把所有的信息都封装在构造函数中,而通过在构造函数中初始化原型(仅在必要的情况下),保存了组合模式的优点。
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; if (typeof this.sayName !== "function") { Person.prototype.sayName = function() { alert(this.name); }; } }
七、寄生构造函数模式
该模式的基本思想是:创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后在返回新创建的对象。
function Person(name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function() { alert(this.name); }; return o; } var friend = new Person("Haha", 34, "Doctor"); friend.sayName();
此处与工厂模式的区别仅仅是:使用new去调用构造函数。注意在构造函数中没有去使用默认生成的新对象this,并且通过显式的return语句改写了构造函数的默认返回对象。
这个模式可以在特殊的情况下用来为对象创建构造函数。
八、稳妥构造函数模式
JavaScript中的稳妥对象(durable objects),指的是没有公共属性,而且其方法也不引用this的对象。稳妥对象适合在一些安全的环境中(禁止this和new),或者防止数据被其他应用程序改动时使用。
function Person(name, age, job) { var o = new Object(); // 可在此处定义室友变量和函数 // 添加方法 o.sayName = function() { alert(name); }; return o; }
注意:此种模式创建的对象中,除了使用sayName()方法之外,没有其他办法访问name的值。
关于JavaScript中的创建对象的学习总结的更多相关文章
- JavaScript 中 关于 this 的学习笔记
今天上午主要学习了js中的 this ,因为之前学习面向对象时,this这个东西出现的还是很频繁的,理解的很不透彻,感觉老被JAVA的思想带进坑里,所以对它特别关注. 首先贴一个大神的一篇博客,我是通 ...
- JavaScript中关于创建对象的笔记
1,最基本的两种创建对象的方式:构造函数|| 字面量 构造函数: var person = new Object(); person.name = "chen1zee1"; per ...
- Javascript中回调函数的学习笔记
function a_b(kkis){ document.body.style.background ='red'; kkis(); } function fli(){ alert('######## ...
- 详解JavaScript中的Object对象
Object是在javascript中一个被我们经常使用的类型,而且JS中的所有对象都是继承自Object对象的.虽说我们平时只是简单地使用了Object对象来存储数据,并没有使用到太多其他功能,但是 ...
- 全面理解Javascript中Promise
全面理解Javascript中Promise 最近在学习Promise的时候,在网上收集了一些资料,发现很多的知识点不够系统,所以小编特意为大家整理了一些自认为 比较好的文章,供大家更好地学习js中非 ...
- Javascript中的Object对象
Object是在javascript中一个被我们经常使用的类型,而且JS中的所有对象都是继承自Object对象的.虽说我们平时只是简单地使用了Object对象来存储数据,并没有使用到太多其他功能,但是 ...
- 深入理解JavaScript中创建对象模式的演变(原型)
深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...
- Javascript中String对象的的简单学习
第十一课String对象介绍1:属性 在javascript中可以用单引号,或者双引号括起来的一个字符当作 一个字符对象的实例,所以可以在某个字符串后再加上.去调用String 对象 ...
- Javascript学习1 - Javascript中的类型对象
原文:Javascript学习1 - Javascript中的类型对象 1.1关于Numbers对象. 常用的方法:number.toString() 不用具体介绍,把数字转换为字符串,相应的还有一个 ...
随机推荐
- chrome断点调试
chrome断点调试 在编写JavaScript代码时,如果出现了bug,就要不断的去找错误,如果console控制台中提示还好说,可是没有提示恐怕就要费一番周折了.但是有了chrome这个浏览器,我 ...
- href和src的使用场景
href和src的使用场景 href和src的用法虽然简单,但是有时候会突然记不起来该怎么用,且两者不可相互替换,下面列出来方便记忆,并给出具体区别. href的使用: 1.外部css引用:<l ...
- DataReader和DataSet的异同
DataReader:使用时始终占用SqlConnection,在线操作数据库:每次只在内存中加载一条数据,所以占用的内存是很小的:是只进的. 只读的. DataSet:则是将数据一次性加载在内存中. ...
- git push to nas
1 建nas目录 在nas的/volume1/git_repos目录下新建相关的目录,并在该目录下运行git init --bare cd /volume1/git_repos mkdir wifi_ ...
- C#中字符串的操作
1.Replace(替换字符):public string Replace(char oldChar,char newChar);在对象中寻找oldChar,如果寻找到,就用newChar将oldCh ...
- MySQL的mysqldump工具的基本用法
导出要用到MySQL的mysqldump工具,基本用法是: shell> mysqldump [OPTIONS] database [tables] 如果你不给定任何表,整个数据库将 ...
- C++ 内存管理与堆栈
/*内存管理与堆栈: * # 一个由C/C++编译的程序占用的内存分为以下几个部分 * 1.栈区:由编译器自动分配释放,数据先进后出 * 2.堆区:由程序员手动分配释放,数据先进先出, * new 和 ...
- js获取锚点名称 #
var thisId = window.location.hash; alert(thisId); 输出 #2
- js数字、字符串、数组之间的转化
1.数组转字符串 var a, b; a = ,,,,); b = a.join("-"); 2.字符串转数组 var s = "abc,abcd,aaa"; ...
- Unity 播放 视频
Unity3D 播放视频 http://www.cnblogs.com/fortomorrow/archive/2012/11/01/unity07.html Unity3D研究院之两种方式播放游戏视 ...