javascript面向对象程序设计(一)

前端之家收集整理的这篇文章主要介绍了javascript面向对象程序设计(一)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

注释里讲解的十分细致了,这里就不多废话了,直接上代码

2004){ this._year=value; this.edition +=value-2004; } } }); book.year=2005; alert(book.edition);//2 //创建对象 //1、将构造函数当做函数 function Person(name,age,job) { this.name=name; this.age=age; this.job=job; this.sayName=function(){ alert(this.name); } } //当做构造函数使用 var person=new Person("xulei",23,"software"); person.sayName(); //作为普通函数使用 Person("xulei2","job2");//添加到window中 window.sayName(); //在另一个对象的作用域中调用 var o=new Object(); Person.call(o,"xulei3","job3"); o.sayName();

再来一段:

//1、无论什么时候,只要创建了一个<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>,就会根据一组特定的规则,为该<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>创建一个prototype<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>,该<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>指向<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>的原型对象 //在默认情况下,所有的原型对象都会<a href="/tag/zidong/" target="_blank" class="keywords">自动</a>获得一个constructor(构造<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>)<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>,这个<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>包含一个指向prototype<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>所在<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>的指针 //如 function Person(){ } //Person.prototype.constructor 指向Person //创建了<a href="/tag/zidingyi/" target="_blank" class="keywords">自定义</a>的构造<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>之后,其原型对象默认只会取得constructor<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>,至于其他<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>则都是从Object继承而来 //当<a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a><a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>的创建一个新实例之后,该实例的内部包含一个指针(内部<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>)指向构造<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>的原型对象 //在Firefox、safari、chrome在每个对象上都<a href="/tag/zhichi/" target="_blank" class="keywords">支持</a>一个<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>_proto_访问 var p1=new Person(); alert(Person.prototype.isPrototypeOf(p1)) alert(Object.getPrototypeOf(p1)==Person.prototype) //虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。如果我们在实例中<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>了一个<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a> //而该<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>的<a href="/tag/mingcheng/" target="_blank" class="keywords">名称</a>与原型的中的实例同名,那我们就在实例中创建该<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>,该<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>将会<a href="/tag/pingbi/" target="_blank" class="keywords">屏蔽</a>原型中的那个<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>。eg: function Person() { } Person.prototype.name="amber"; Person.prototype.age=23; Person.prototype.job="software engineer"; Person.prototype.sayName=function(){ alert(this.name) } var person1=new Person(); var person2=new Person(); person1.name="amber.Xu"; alert(person1.name);//amber.xu --来自实例 alert(person2.name);//amber --来自原型 delete person1.name; alert(person1.name);//amber --来自原型 //使用hasOwnProperty()<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>可以检测一个<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>是存在于实例中还是存在于原型中,这个<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>(从Object继承而来) //只在给定<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>存在于对象实例中时,才会返回true function Person() { } Person.prototype.name="amber"; Person.prototype.age=23; Person.prototype.job="software engineer"; Person.prototype.sayName=function(){ alert(this.name) } var person1=new Person(); var person2=new Person(); alert(person1.hasOwnProperty("name"));//false 来自实例 alert(person2.hasOwnProperty("name"));//false 来自实例 person1.name="amber.xu"; alert(person1.name); alert(person1.hasOwnProperty("name"));//true 来自实例 delete person1.name; alert(person1.name); alert(person1.hasOwnProperty("name"));//false 来自原型 //2、原型与in操作符 //in 有两种使用方式,一个是的单独使用和在for-in 中使用。在单独使用时,in操作符会在对象能够访问给定<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>时返回true //无论该<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>时来自原型还是实例 function Person() { } Person.prototype.name="amber"; Person.prototype.age=23; Person.prototype.job="software engineer"; Person.prototype.sayName=function(){ alert(this.name) } var person1=new Person(); var person2=new Person(); alert("name" in person1);//true 来自原型 alert("name" in person2);//true 来自原型 alert("height" in person1);//false //这样就可以封装一个<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>(给定<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>是否是来给定对象的原型) function hasPrototypeProperty(object,name){ return !object.hasOwnProperty(name) && (name in object); } alert("----------------------------------"); alert(hasPrototypeProperty(person1,"name"));//true person1.name="张三"; alert(hasPrototypeProperty(person1,"name"));//false //使用for-in 返回的是所有能够通过对象访问、可枚举的<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>,其中既包含原型<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>也包含实例<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>。 //<a href="/tag/pingbi/" target="_blank" class="keywords">屏蔽</a>了原型中不可枚举<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>(将Enumerable<a href="/tag/biaoji/" target="_blank" class="keywords">标记</a>为false的<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>)的实例<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>也会在for-in中返回 //ie早期版本总中有一个bug:<a href="/tag/pingbi/" target="_blank" class="keywords">屏蔽</a>了原型中不可枚举<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>的实例<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>也不会在for-in中返回 //eg: var o={ toString:function(){ return "my object"; } }; for(var prop in o){ if(prop=="toString"){ alert("找到了");//在ie早期版本中不会<a href="/tag/xianshi/" target="_blank" class="keywords">显示</a> } } //要取得对象上所有可枚举的<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>,可以使用ECMAScript5的Object.keys()<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>。接受一个对象作为参数, //包含所有可枚举<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>的字符串数组 function Person() { } Person.prototype.name="amber"; Person.prototype.age=23; Person.prototype.job="software engineer"; Person.prototype.sayName=function(){ alert(this.name) } var person1=new Person(); var person2=new Person(); var keys=Object.keys(Person.prototype); alert(keys) person1.name="amber.Xu"; person1.age=23; var keys=Object.keys(person1); alert(keys) alert("-----------------------------------------") //如果想要得到所有的实例<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>不管他是否可以枚举,都可以使用 alert(Object.getOwnPropertyNames(person1)); alert(Object.getOwnPropertyNames(Person.prototype)); alert("更简单的原型语法-----------------------------------------") //3、更简单的原型语法 function Person() { } Person.prototype={ name:"AMBER",age:23,job:"software",sayName:function(){ alert(this.name) } } //这样写之后constructor<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>不再指向Person<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>,而是指向Object构造<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>。 //尽管通过instanceof操作符还能返回正确的结果,但是通过constructor已经无法确定对象的类型了,eg: var friend=new Person(); alert(friend instanceof Person)//true alert(friend instanceof Object)//true alert(friend.constructor==Person);//false alert(friend.constructor==Object);//true //如果constructor对你真的很重要,可以向下面一样设置成适当的值 function Person() { } Person.prototype={ constructor:Person,name:"AMBER",sayName:function(){ alert(this.name) } } var friend=new Person(); alert("手动设置constructor-----------------------------------------") alert(friend.constructor==Person);//true //这种手动的<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>了constructor会使constructor变成可枚举的元(原生的constructor<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>时不可枚举的)。 //这种情况下就可以使用 Object.defineProperty(Person.prototype,"constructor",{ enumerable:false,value:Person }); //原型的动态性 var friend=new Person(); Person.prototype.sayHi=function(){ alert("Hi"); } friend.sayHi();//Hi (正常执行) //因为实例和原型之间是松散的连接关系,实例与原型之间的连接只不过是一个指针,而非副本 //当我们<a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a>sayHi()<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>时,首先会在实例中<a href="/tag/sousuo/" target="_blank" class="keywords">搜索</a>名为sayHi的<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>,在没找到的情况下会<a href="/tag/sousuo/" target="_blank" class="keywords">搜索</a>原型。 //但是,如果是重写整个原型对象,那么情况就不一样了。 //我们知道,<a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a>构造<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>时会为实例<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>一个指向最初原型的Prototype指针,而把原型<a href="/tag/xiugai/" target="_blank" class="keywords">修改</a>为另一个对象就等于切断了构造<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>与最初原型之间的联系。 //请记住:实例中的指针仅指向原型,而不指向构造<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>。eg: function A(){} var a1=new A(); A.prototype={ constructor:A,sayName:function(){ alert(this.name) } } alert("ERROR-------------------------------------"); alert(a1.sayName()); //我们创建了一个A的实例,然后又重写了其原型对象,然后在<a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a>a1.sayName()发生了<a href="/tag/cuowu/" target="_blank" class="keywords">错误</a>,因为a指向的原型中不包含以该名字命名的<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>/<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a> //原生对象的原型 //原型模式的重要性不仅体现在创建<a href="/tag/zidingyi/" target="_blank" class="keywords">自定义</a>类型方面。就连所有的原生的引用类型,都是采用这种模式创建的。所有的原生引用类型 //都在其构造<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>的原型上定义的<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a> eg: alert(typeof Array.prototype.sort);//function alert(typeof String.prototype.substring);//function //不仅可以在原生对象的原型取得虽有默认<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>的引用,而且可以定义新的<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a> //为String类型<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>一个startsWith()的<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a> String.prototype.startsWith=function(text){ return this.indexOf(text) == 0; }; var msg="Hello"; alert(msg.startsWith("H")); //我们并不建议这样做。 alert("原型对象的问题"); //6、原型对象的问题 实例 function Ques() { } Ques.prototype={ constructor:Ques,name:"amber",job:"IT",friends:["张三","李四"],//引用类型 sayName:function(){ alert(this.name) } }; var q1=new Ques(); var q2=new Ques(); q1.friends.push("王五"); alert(q1.friends);// alert(q2.friends);// alert(q1.friends===q2.friends);

//相信大家已经看到了问题,当我创建了两个实例q1、q2,当我为q1的“朋友”添加了“王五”之后,q2的”朋友“也有了三个张三、李四、王五
//那是因为数组存在于Ques.prototype上,而非q1上。所以出现了如上结果。

//而正是这个问题,我们很少看到有人单独使用原型模式的原因所在。

本文就先到这里了,后续我们再继续讨论javascript面向对象程序设计,希望大家能够喜欢。

猜你在找的JavaScript相关文章