javascript面向?qū)ο蟪绦蛟O(shè)計(一)
更新時間:2015年01月29日 09:36:16 投稿:hebedich
這篇文章主要介紹了javascript面向?qū)ο蟪绦蛟O(shè)計,分享給大家一段代碼,注釋里講解的非常詳細(xì),有助于我們理解面向?qū)ο?,這里推薦給大家。
注釋里講解的十分細(xì)致了,這里就不多廢話了,直接上代碼:
<script type="text/javascript">
//ECMA-262把對象定義為:“無序?qū)傩缘?集合,其屬性可以包含基本值、對象或者函數(shù)”
//理解對象,最簡單的方式就是通過創(chuàng)建一個Object的實(shí)例,然后為它添加屬性和方法
var person = new Object();
person.name = "Xulei";
person.age = "23";
person.job = "前端工程師";
person.sayName = function () {
alert(this.name);
}
//還可以這樣寫
var person = {
name: "xulei",
age: 23,
job: "前端工程",
sayName: function () {
alert(this.name)
}
}
//一、屬性類型:數(shù)據(jù)屬性和訪問其屬性
//1、數(shù)據(jù)屬性,有4個描述其行為的特性
//[Configurable]:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性,默認(rèn)值為true
//[Enumerable]:表示能否通過for-in返回屬性,默認(rèn)值為true
//[Writable]:表示能否修改屬性,默認(rèn)值為true
//[Value]:包含這個屬性的數(shù)據(jù)值。默認(rèn)值為undefined
var person = {
name: "xulei"
}
//這里創(chuàng)建了一個person對象,value值就是“xulei”
//要修改屬性的默認(rèn)特性,必須使用ECMAScript5的Object.defineProperty(屬性所在的對象,屬性的名字,描述符對象)
//描述符對象必須是configurable、enumerable、writable、value
var peron = {}
Object.defineProperty(peron, "name", {
writable: false,//屬性不能被修改
value: "徐磊-xulei"
});
alert(peron.name);//徐磊-xulei
peron.name = "徐磊";
alert(peron.name);//徐磊-xulei
//以上操作在非嚴(yán)格模式下賦值操作會被忽略,如果在嚴(yán)格模式下會拋出異常
//一旦把屬性定義為不可配置的就不能把它變回可配置的了。
//在多數(shù)情況下都沒有必要利用Object.defineProperty()方法提供的這些高級功能。但是對理解javascript非常有用。
//建議讀者不要在ie8上使用此方法。
//2、訪問其屬性,有4個特性
//[Configurable]:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性,默認(rèn)值為true
//[Enumerable]:表示能否通過for-in返回屬性,默認(rèn)值為true
//[Get]:在讀取時調(diào)用的函數(shù) 默認(rèn)值undefined
//[Set]:在寫入屬性時調(diào)用的函數(shù) 默認(rèn)值Undefined
var book={
_year:2004,
edition:1
}
Object.defineProperty(book,"year",{
get:function(){
return this._year;
},
set:function(value){
if(value>2004){
this._year=value;
this.edition +=value-2004;
}
}
});
book.year=2005;
alert(book.edition);//2
//創(chuàng)建對象
//1、將構(gòu)造函數(shù)當(dāng)做函數(shù)
function Person(name,age,job) {
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
alert(this.name);
}
}
//當(dāng)做構(gòu)造函數(shù)使用
var person=new Person("xulei",23,"software");
person.sayName();
//作為普通函數(shù)使用
Person("xulei2",23,"job2");//添加到window中
window.sayName();
//在另一個對象的作用域中調(diào)用
var o=new Object();
Person.call(o,"xulei3",23,"job3");
o.sayName();
</script>
再來一段:
<script type="text/javascript">
//1、理解原型對象
//2、原型與in操作符
//3、更簡單的原型語法
//4、原型的動態(tài)性
//5、原生對象原型
//6、原型對象的問題
//1、無論什么時候,只要創(chuàng)建了一個函數(shù),就會根據(jù)一組特定的規(guī)則,為該函數(shù)創(chuàng)建一個prototype屬性,該屬性指向函數(shù)的原型對象
//在默認(rèn)情況下,所有的原型對象都會自動獲得一個constructor(構(gòu)造函數(shù))屬性,這個屬性包含一個指向prototype屬性所在函數(shù)的指針
//如
function Person(){
}
//Person.prototype.constructor 指向Person
//創(chuàng)建了自定義的構(gòu)造函數(shù)之后,其原型對象默認(rèn)只會取得constructor屬性,至于其他方法則都是從Object繼承而來
//當(dāng)調(diào)用函數(shù)的創(chuàng)建一個新實(shí)例之后,該實(shí)例的內(nèi)部包含一個指針(內(nèi)部屬性)指向構(gòu)造函數(shù)的原型對象
//在Firefox、safari、chrome在每個對象上都支持一個屬性_proto_訪問
var p1=new Person();
alert(Person.prototype.isPrototypeOf(p1))
alert(Object.getPrototypeOf(p1)==Person.prototype)
//雖然可以通過對象實(shí)例訪問保存在原型中的值,但卻不能通過對象實(shí)例重寫原型中的值。如果我們在實(shí)例中添加了一個屬性
//而該屬性的名稱與原型的中的實(shí)例同名,那我們就在實(shí)例中創(chuàng)建該屬性,該屬性將會屏蔽原型中的那個屬性。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 --來自實(shí)例
alert(person2.name);//amber --來自原型
delete person1.name;
alert(person1.name);//amber --來自原型
//使用hasOwnProperty()方法可以檢測一個屬性是存在于實(shí)例中還是存在于原型中,這個方法(從Object繼承而來)
//只在給定屬性存在于對象實(shí)例中時,才會返回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 來自實(shí)例
alert(person2.hasOwnProperty("name"));//false 來自實(shí)例
person1.name="amber.xu";
alert(person1.name);
alert(person1.hasOwnProperty("name"));//true 來自實(shí)例
delete person1.name;
alert(person1.name);
alert(person1.hasOwnProperty("name"));//false 來自原型
//2、原型與in操作符
//in 有兩種使用方式,一個是的單獨(dú)使用和在for-in 中使用。在單獨(dú)使用時,in操作符會在對象能夠訪問給定屬性時返回true
//無論該屬性時來自原型還是實(shí)例
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
//這樣就可以封裝一個函數(shù)(給定屬性是否是來給定對象的原型)
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 返回的是所有能夠通過對象訪問、可枚舉的屬性,其中既包含原型屬性也包含實(shí)例屬性。
//屏蔽了原型中不可枚舉屬性(將Enumerable標(biāo)記為false的屬性)的實(shí)例屬性也會在for-in中返回
//ie早期版本總中有一個bug:屏蔽了原型中不可枚舉屬性的實(shí)例屬性也不會在for-in中返回
//eg:
var o={
toString:function(){
return "my object";
}
};
for(var prop in o){
if(prop=="toString"){
alert("找到了");//在ie早期版本中不會顯示
}
}
//要取得對象上所有可枚舉的屬性,可以使用ECMAScript5的Object.keys()方法。接受一個對象作為參數(shù),
//包含所有可枚舉屬性的字符串?dāng)?shù)組
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("-----------------------------------------")
//如果想要得到所有的實(shí)例屬性不管他是否可以枚舉,都可以使用
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屬性不再指向Person函數(shù),而是指向Object構(gòu)造函數(shù)。
//盡管通過instanceof操作符還能返回正確的結(jié)果,但是通過constructor已經(jīng)無法確定對象的類型了,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對你真的很重要,可以向下面一樣設(shè)置成適當(dāng)?shù)闹?
function Person() {
}
Person.prototype={
constructor:Person,
name:"AMBER",
age:23,
job:"software",
sayName:function(){
alert(this.name)
}
}
var friend=new Person();
alert("手動設(shè)置constructor-----------------------------------------")
alert(friend.constructor==Person);//true
//這種手動的添加了constructor會使constructor變成可枚舉的元(原生的constructor屬性時不可枚舉的)。
//這種情況下就可以使用
Object.defineProperty(Person.prototype,"constructor",{
enumerable:false,
value:Person
});
//原型的動態(tài)性
var friend=new Person();
Person.prototype.sayHi=function(){
alert("Hi");
}
friend.sayHi();//Hi (正常執(zhí)行)
//因?yàn)閷?shí)例和原型之間是松散的連接關(guān)系,實(shí)例與原型之間的連接只不過是一個指針,而非副本
//當(dāng)我們調(diào)用sayHi()方法時,首先會在實(shí)例中搜索名為sayHi的方法,在沒找到的情況下會搜索原型。
//但是,如果是重寫整個原型對象,那么情況就不一樣了。
//我們知道,調(diào)用構(gòu)造函數(shù)時會為實(shí)例添加一個指向最初原型的Prototype指針,而把原型修改為另一個對象就等于切斷了構(gòu)造函數(shù)與最初原型之間的聯(lián)系。
//請記?。簩?shí)例中的指針僅指向原型,而不指向構(gòu)造函數(shù)。eg:
function A(){}
var a1=new A();
A.prototype={
constructor:A,
name:"AMBER",
age:23,
job:"software",
sayName:function(){
alert(this.name)
}
}
alert("ERROR-------------------------------------");
alert(a1.sayName());
//我們創(chuàng)建了一個A的實(shí)例,然后又重寫了其原型對象,然后在調(diào)用a1.sayName()發(fā)生了錯誤,因?yàn)閍指向的原型中不包含以該名字命名的屬性/方法
//原生對象的原型
//原型模式的重要性不僅體現(xiàn)在創(chuàng)建自定義類型方面。就連所有的原生的引用類型,都是采用這種模式創(chuàng)建的。所有的原生引用類型
//都在其構(gòu)造函數(shù)的原型上定義的方法 eg:
alert(typeof Array.prototype.sort);//function
alert(typeof String.prototype.substring);//function
//不僅可以在原生對象的原型取得雖有默認(rèn)方法的引用,而且可以定義新的方法
//為String類型添加一個startsWith()的方法
String.prototype.startsWith=function(text){
return this.indexOf(text) == 0;
};
var msg="Hello";
alert(msg.startsWith("H"));
//我們并不建議這樣做。
alert("原型對象的問題");
//6、原型對象的問題 實(shí)例
function Ques() {
}
Ques.prototype={
constructor:Ques,
name:"amber",
age:23,
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);
//相信大家已經(jīng)看到了問題,當(dāng)我創(chuàng)建了兩個實(shí)例q1、q2,當(dāng)我為q1的“朋友”添加了“王五”之后,q2的”朋友“也有了三個張三、李四、王五
//那是因?yàn)閿?shù)組存在于Ques.prototype上,而非q1上。所以出現(xiàn)了如上結(jié)果。
//而正是這個問題,我們很少看到有人單獨(dú)使用原型模式的原因所在。
</script>
本文就先到這里了,后續(xù)我們再繼續(xù)討論javascript面向?qū)ο蟪绦蛟O(shè)計,希望大家能夠喜歡。
相關(guān)文章
微信小程序之ES6與事項助手的功能實(shí)現(xiàn)
本篇文章主要介紹了微信小程序之ES6與事項助手的功能實(shí)現(xiàn),具有一定的參考價值,有興趣的同學(xué)可以了解一下。2016-11-11
echarts學(xué)習(xí)筆記之圖表自適應(yīng)問題詳解
最近發(fā)現(xiàn)一個問題,echarts圖初始化后不能自適應(yīng)瀏覽器的縮放,所以下面這篇文章就來給大家介紹了關(guān)于echarts圖表自適應(yīng)問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11
js拆分字符串并將分割的數(shù)據(jù)放到數(shù)組中的方法
這篇文章主要介紹了js拆分字符串并將分割的數(shù)據(jù)放到數(shù)組中的方法,涉及javascript中split方法及數(shù)組的操作技巧,需要的朋友可以參考下2015-05-05
javascript實(shí)現(xiàn)檢驗(yàn)的各種規(guī)則
這篇文章主要介紹了javascript實(shí)現(xiàn)檢驗(yàn)的各種規(guī)則,涉及javascript針對手機(jī)號、郵箱、網(wǎng)址、漢字及圖片等相關(guān)檢測技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07

