封装——JavaScript的原型(prototype)
来源:互联网 发布:dota2比赛视频软件 编辑:程序博客网 时间:2024/05/16 09:08
prototype,原型的初览
function Person(){Person.prototype.name="小花";Person.prototype.age=18;Person.prototype.say=function(){alert("姓名:"+this.name+",年龄:"+this.age);}}var p1=new Person();p1.say();say();//报错了
这样我们发现window就无法访问到say方法了,此时say方法只属于person对象独有的方法。很好的解决了封装破坏的情况。
什么是原型
上面我们烂了基于prototype创建对象的方式很好的解决了我们前面遇到的一系列问题,那么到底什么是原型,原型又是如何解决以上的问题的呢?我们下面来研究研究。
原型是js中非常特殊一个对象,当一个函数创建之后,会随之产生一个原型对象,当通过这个函数的构造函数创建了一个具体的对象之后,在这个具体的对象中就会有一个属性指向原型。这就是原型的概念。
鉴于原型的概念比较难以理解,我们就以上面的代码为例,画图为大家讲解。
第一步:function Person(){}之后,内存中创建了一个Person对象,有一个prototype属相,指向了Person对象的原型对象,而原型对象中存在了一个constructor的属性,指向了Person对象。
第三种状态:当根据Person构造函数创建一个对象后,该对象中存在一个_prop_的属性,也指向了Person对象的原型对象,当我们调用对象的属性或者方法时,首先在自己里面找,找不到的话,就会去Person对象的原型对象中找
原型的基本知识到这里也就差不多了,只有对上面的图和代码能够很好的理解,那么原型的理解就没问题,下面介绍几种原型的检测方式。
alert(Person.prototype.isprototypeof(p1))//检测p1的构造函数是否指向Person对象alert(p1.constructor==Person)//检测某个属性是不是自己内存中的alert(p1.hasOwnProperty("name"));可以使用delete语句来删除我们赋予对象的自己属性(注意:原型中的是无法删除的)如:
delete p1.name;p1.say();alert(p1.hasOwnProperty("name"));检测在某个对象自己或者对应的原型中是否存在某个属性。
alert("name" in p1);//true delete p2.name;//虽然删除了自己的name属性,但是原型中有alert("name" in p2);//true //原型和自己中都有sex属性alert("sex" in Person)//false那么问题来了。如果检测只在原型中,不在自己的属性呢?
function hasPP(obj,prop){if(!obj.hasOwnProperty(prop)){if(prop in obj){return true;}}return false;}alert(hasPP(p1,"name"));alert(hasPP(p2,"name"));原型重写
在上面的写法中,我们已经解决了大量的问题,使用原型。但是如果我们的对象中存在大量的属性或者方法的时候,使用上面的方式,感觉要写大量的【对象.prototype.属性名】这样的代码,感觉不是很好,那么我们可以使用JSON的方式来写:
function Person(){}Person.prototype={name:"刘帅哥";age:18;say:function(){alert("姓名:"+this.name+",年龄:"+this.age);}}var p1=new Person();p1.say();var p2=new Person();p2.age=20;p2.name="小明";p2.say();但是这种写法,我们是将该对象的原型覆盖(注意:这两种写法不一样的,第一种是扩充,第二种是覆盖),就会出现如下的问题:
function Person(){}Person.prototype={name:"刘帅哥";age:18;say:function(){alert("姓名:"+this.name+",年龄:"+this.age);}}var p1=new Person();p1.say();var p2=new Person();p2.age=20;p2.name="小明";p2.say();//此时p1的构造器不再指向Person,而是指向了Object//因为我们覆盖了Person的原型,所以如果constructor比较重要的话,//我们可以收到指向alert(p1.constructor==Person)此时就没有问题了。但是原型重写会给我们带来非常有趣的现象。
function Person(){}var p1=new Person();Person.prototype.sayHello=function(){alert("名字:"+this.name+",年龄:"+this.age);}Person.prototype={constructor:Person,name:"huahua",age:18,friends:["haha","xxx"],say:function(){alert("名字:"+this.name+",年龄:"+this.age);}}var p2=new Person();p2.say();//正确p1.sayHello();//此时找不到name和age,但是代码正确p1.say();//错误,因为原型重写p2.sayHello();//错误这些代码要研究明白,必须配合之前原型的图来看,下面我画图来说明问题:
因为原型重写,需要大家根据原型的原理图来理解,原型的知识也就这些了。
封装——原型创建对象
因为原型存在,我们事先了对象的封装,但是这种封装也同样可能存在问题的。
1.我们无法像使用构造函数的那样将属性传递用于设置值
2.当属性中引用类型,可能存在变量值的重复
function Person(){};Person.prototype={constructor:Person,name:"huahua",age:18,friends:["haha","xxx"],say:function(){alert(this.name+this.age+this.friends);}}var p1=new Person();p1.say();var p2=new Person;p2.name="xiaocao";p2.say();p1.friends.push("qq");alert(p1.friends);//qqalert(p2.friends);//qq //因为p1和p2对象都指向了同一个原型链,所以当p1属性值发生变化时,p2也变化,p2的输出也和p1一样终极方案——基于组合的对象定义
为了解决原型所带来的问题,需要通过组合构造函数和原型来实现对象的创建将:属相在构造函数中定义,将方法在原型中定义。这种有效集合了两者的优点,是目前最为常用的一种方式。
//所以需要通过组合的封装构造函数和原型来实现对象的创建//基于组合的对象定义//即属性在构造方法中定义,方法在原型中定义function Person(name,age,friends){this.name=name;this.age=age;this.friends=friends;}//此时所有的属性都保存在自己的内存中Person.prototype={constructor:Person,say:function(){alert(this.name+this.age+this.friends);}}//方法定义在原型中var p1=new Person("花猫",19,["小花","小妹"]);p1.friends.push("豆豆");alert(p1.friends);var p2=new Person("黑猫",19,["小草","小妹"]);p2.friends.push("南瓜");alert(p2.friends);//基于动态原型的对象定义function Person(name,age,friends){this.name=name;this.age=age;this.friends=friends;//判断不存在的时候写//如果存在就不写,减少内存消耗if(!Person.prototype.say){Person.prototype.say=function(){alert(this.name+this.age+this.friends);}}}var p1=new Person("花猫",19,["小花","小妹"]);p1.friends.push("豆豆");alert(p1.friends);var p2=new Person("黑猫",19,["小草","小妹"]);p2.friends.push("南瓜");alert(p2.friends);JavaScript面向对象对应一个对象的方式,上述两种都行,根据个人习惯而定。这也是JavaScript中面向对象的封装。将属性和方法封装所对应的对象中,其他对象无法得到和访问。
1 0
- 封装——JavaScript的原型(prototype)
- 封装--javascript的原型(prototype)
- 封装--javascript的原型(prototype)
- JavaScript的prototype(原型)
- javascript 原型(prototype)
- 【JavaScript 封装库】Prototype 原型版发布!
- 浅析JavaScript的原型(prototype)(一)
- javascript面向对象——prototype属性(原型属性)
- JavaScript的原型对象(prototype)——函数的&对象的
- 【Javascript基础篇】—--原型对象(prototype)的三个常用方法
- JavaScript 的原型对象 Prototype
- javascript原型prototype的由来
- javaScript prototype原型的理解
- JavaScript原型(prototype)小记
- 深入理解javascript原型和闭包(3)——prototype原型
- 深入理解javascript原型和闭包(3)——prototype原型
- 深入理解javascript原型和闭包(3)——prototype原型
- 深入理解javascript原型和闭包(3)——prototype原型
- C++(static使用注意,和非static区别)
- 二分图匹配——匈牙利算法の板子
- scp 使用
- C# 易忽略的知识
- 自定义的删除edittext
- 封装——JavaScript的原型(prototype)
- Android广播和服务
- 解决eclipse生成javadoc出现错误“编码 GBK 的不可映射字符”
- ARM汇编指令学习方法
- linux sudo提权
- 25个经典的Spring面试问答
- javascript基础笔记(四)之js里面的语句
- 23种设计模式
- eclipse中 配置显示JDK代码 问题