摘要:前言虽然使用构造函数或者使用对象字面量可以很方便的用来创建一个对象,但这种方式有一个明显的缺点使用一个接口创建多个对象会产生很多冗余的代码。即调用构造函数所创建的那个对象的原型对象好处是可以让所有对象的实例共享他的属性的方法。
前言
虽然使用Object构造函数或者使用对象字面量可以很方便的用来创建一个对象,但这种方式有一个明显的缺点:使用一个接口创建多个对象会产生很多冗余的代码。因此为了解决这个问题,人们开始使用以下几种方式来常见对象。
工厂模式该模式抽象了创建对象的具体过程,用函数来以特定接口创建对象的细节
function cPerson(name,sex,age){ var o = new Object(); o.name = name; o.sex = sex; o.age = age; o.show = function(){ console.log(this.name,this.age,this.sex); } return o; } var p1 = cPerson("谦龙","男","100"); p1.show(); var p2 = cPerson("雏田","女","14"); p2.show();
工厂模式测试
工厂方式的问题:使用工厂模式能够创建一个包含所有信息的对象,可以无数次的调用的这个函数。虽然其解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即如何得知一个对象的类型)
function CPerson(name,sex,age) {//注意这里 构造函数首字母大写 this.name = name; this.sex = sex; this.age = age; this.show = function () { console.log(this.name, this.age, this.sex); } } var p1 = new CPerson("谦龙","男","100"); p1.show(); var p2 = new CPerson("雏田","女","14"); p2.show();
构造函数模式测试
注意构造函数与工厂模式有些不同的地方,如下
构造函数首字母大写
没有显式地创建对象
将属性和方法赋值给了 this对象
没有return语句
而且以这种方式来调用构造函数会大致经历一下几个步骤
创建一个新的对象
将构造函数的作用域赋值给这个对象(因此this就指向了这个对象)
执行构造函数中的代码(即给新对象添加属性和方法的过程)
返回对象
注意:构造函数其实和普通的函数没有太大的差别,唯一的不同在于调用方式的不同。以下演示不同的几种调用方式
// 调用方式1 new 方式 var p1 = new CPerson("谦龙","男","100"); p1.show();//谦龙 100 男 // 调用方式2 普通函数调用 CPerson("谦龙","男","100"); window.show()//谦龙 100 男 注意属性和方法会被设置到window对象上 // 调用方式3 在另一个对象的作用域中调用 var obj = new Object(); CPerson.call(obj,"谦龙","男","100"); obj.show(); //谦龙 100 男 在obj的作用域
构造函数的问题:使用构造函数最主要的问题就是每个方法都要在每个实例上重新创建一次,p1与p2的都有show方法,但不是同一个Function的实例,因为function在js中也是一个对象。因此他们共有的show方法并不相等。
原型模式每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象。而这个对象的用途是 包含可以由特定类型的所有实例 共享的属性和方法。即调用构造函数所创建的那个对象的 原型对象
好处是可以让所有对象的实例共享他的属性的方法。即无需在构造函数中定义实例的信息
function CPerson(){ } CPerson.prototype.name="谦龙"; CPerson.prototype.sex="男"; CPerson.prototype.age=100; CPerson.prototype.show=function(){ console.log(this.name, this.age, this.sex); } var p1 = new CPerson(); p1.show(); //谦龙 100 男 var p2 = new CPerson(); p2.show();//谦龙 100 男 console.log(p1.show == p2.show)//true
原型模式测试
由上图可知p1与p2共享属性和方法
原型模式的问题:
省略了为构造函数传递初始化参数,导致默认情况下所有实例将得到相同的属性值
所有属性都会被实例所共享,当属性的类型是引用类型的时候会出一定的问题,实例间对该属性的修改会相互影响
针对以上所说的第二个问题我们给出实例
function CPerson(){ } CPerson.prototype.name="谦龙"; CPerson.prototype.sex="男"; CPerson.prototype.age=100; CPerson.prototype.job=["前端","后端"]; CPerson.prototype.show=function(){ console.log(this.name, this.age, this.sex); } var p1 = new CPerson(); p1.job.push("测试"); console.log(p1.job);//["前端", "后端", "测试"] var p2 = new CPerson(); console.log(p2.job);//["前端", "后端", "测试"] console.log(p1.job == p2.job);// true
测试
由以上可以看出,两个对象p1,p2对job的修改会相互影响,但按照正常思维,实例一般要有自己的全部的属性。
组合使用构造函数和原型模式该方式利用构造函数定义实例属性、利用原型定义方法和共享的属性,结果每个实例都有一份实例属性的副本,而且共享着方法的引用,可谓是集两家之所长。
function CPerson(name,sex,age) {//注意这里 构造函数首字母大写 this.name = name; this.sex = sex; this.age = age; this.job=["前端","后端"]; } CPerson.prototype={ constructor:CPerson,//注意这里 show : function () { console.log(this.name, this.age, this.sex); } } var p1 = new CPerson("谦龙","男",100); var p2 = new CPerson("雏田","女",20); p1.job.push("测试"); console.log(p1.job);//["前端", "后端", "测试"] console.log(p2.job);//["前端", "后端"] console.log(p1.job == p2.job);//fasle console.log(p1.show == p2.show);//true
组合模式测试
说明:这种组合模式是使用最广泛、认同度最高的一种创建自定义类型的方法。
动态原型模式动态原型模式将所有的信息都封装在了函数中,而通过构造函数中初始化原型,保持了同时使用构造函数和原型的优点
function CPerson(name,sex,age) {//注意这里 构造函数首字母大写 this.name = name; this.sex = sex; this.age = age; this.job=["前端","后端"]; if(typeof this.show !="function"){ //注意这里 console.log("just one"); CPerson.prototype.show=function(){ console.log(this.name, this.age, this.sex); } } } var p1 = new CPerson("谦龙","男",100); //just one var p2 = new CPerson("雏田","女",20);//没有输出
动态原型模式测试
该方式的基本思想是创建一个函数,用来封装创建对象的代码,然后再返回新创建的对象。构造函数在不返回值的情况下,默认会返回新对象的实例,而通过return语句可以修改调用构造函数时的返回值。
该方式有一定的应用场景比如,当我们想创建一个具有额外方法的数组而又不能修改Array构造函数的情况下,可以使用这种模式
function MyOwnArray(){ var arr=new Array();//创建新对象 arr.push.apply(arr,arguments); arr.show=function(){ console.log(this.join("|")); } return arr; } var arr1 = new MyOwnArray("谦龙","男",100); arr1.show();
寄生构造函数模式测试
稳妥对象即没有公共属性,方法也不引用this对象,稳妥对象最适合在一些安全的环境中(例如禁止使用this和new)或者防止数据被其他应用程序修改的时候使用。
注意:稳妥构造函数和寄生式构造函数有许多类似的地方,以下是他们的不同之处
不使用new操作符来调用构造函数
创建对象的实例方法不使用this对象
function CPerson(name,sex,age){ var obj = new Object(); // private members var myOwnName="谦龙"; obj.showOwnName=function(){ console.log(myOwnName);//只有通过该方法才能访问myOwnName 私有属性 } obj.show=function(){ console.log(name,sex,age); } return obj; } var p1=CPerson("谦龙","男","100"); p1.show(); p1.showOwnName();
稳妥构造函数模式测试
除了通过调用对应的方法来访问其数据成员,没有别的方法可以访问到原始添加的数据,其提供的这种安全机制适合在例如ADsafe等的环境下使用
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/86157.html
摘要:中的对象无序的属性的集合,属性可以包含基本值对象函数。共有四个描述其行为的特性。返回的是一个对象,如果是数据属性,则返回的属性有如果是访问器属性则返回的属性有对象遍历函数数据属性访问器属性测试 前言 基于类的对象:我们都知道面向对象的语言中有一个明显的标志,就是都有类的概念,通过类这个类似模板的东西我们可以创建许多个具有相同的属性和方法的对象。然而在ECMAScript中并没有类的概...
摘要:有需要还可以修改指向谦龙寄生组合式继承思路是通过借用构造函数来继承属性,通过原型链的混合形式来继承方法改变执行环境实现继承有需要还可以修改指向谦龙谦龙拷贝继承该方法思路是将另外一个对象的属性和方法拷贝至另一个对象使用递归 前言 js中实现继承的方式只支持实现继承,即继承实际的方法,而实现继承主要是依靠原型链来完成的。 原型链式继承 该方式实现的本质是重写原型对象,代之以一个新类型的实例...
阅读 1747·2023-04-25 16:28
阅读 684·2021-11-23 09:51
阅读 1467·2019-08-30 15:54
阅读 1148·2019-08-30 15:53
阅读 2815·2019-08-30 15:53
阅读 3412·2019-08-30 15:43
阅读 3249·2019-08-30 11:18
阅读 3260·2019-08-26 10:25