亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > WEB開發 > 正文

javascript筆記--(第十五章)面向對象與原型

2024-04-27 15:05:00
字體:
來源:轉載
供稿:網友

面向對象

ECMAScript有兩種開發模式:1.函數式(過程化),2.面向對象(OOP)。面向對象的語言有一個標志,那就是類的概念,而通過類可以創建任意多個具有相同屬性和方法的對象。但是,ECMAScript沒有類的概念,因此它的對象也與基于類的語言中的對象有所不同。

工廠方法

解決實例化對象產生大量重復的問題
<script type="text/javascript">	function createObject(name, age) {		//集中實例化的函數		var obj = new Object();		obj.name = name;		obj.age = age;		obj.run = function () {			return this.name + this.age + '運行中...';		};		return obj;	}	var box1 = createObject('Lee', 100);		//第一個實例	var box2 = createObject('Jack', 200);		//第二個實例	console.log(box1.run());	console.log(box2.run());					</script>

構造函數

解決了重復實例化的問題,又解決了對象識別的問題
<script type="text/Javascript">	function Box(name, age) {				//構造函數模式		this.name = name;		this.age = age;		this.run = function () {			return this.name + this.age + '運行中...';		};	}	var box1 = new Box('Lee', 100);			//new Box()即可	var box2 = new Box('Jack', 200);	console.log(box1.run());	console.log(box1 instanceof Box);		//很清晰的識別他從屬于Box		</script>構造函數的方法有一些規范:1.函數名和實例化構造名相同且大寫,(PS:非強制,但這么寫有助于區分構造函數和普通函數);2.通過構造函數創建對象,必須使用new運算符。構造函數實例化對象過程:1.當使用了構造函數,并且new 構造函數(),那么就后臺執行了new Object();2.將構造函數的作用域給新對象,(即new Object()創建出的對象),而函數體內的this就代表new Object()出來的對象。3.執行構造函數內的代碼;4.返回新對象(后臺直接返回)。構造函數和普通函數的唯一區別,就是他們調用的方式不同。只不過,構造函數也是函數,必須用new運算符來調用,否則就是普通函數。
var box = new Box('Lee', 100);			//構造模式調用alert(box.run());Box('Lee', 20);					//普通模式調用,無效var o = new Object();					Box.call(o, 'Jack', 200)			//對象冒充調用alert(o.run());			函數屬性引用問題:
var box1 = new Box('Lee', 100);			//傳遞一致var box2 = new Box('Lee', 100);			//同上alert(box1.name == box2.name);			//true,屬性的值相等alert(box1.run == box2.run);			//false,方法其實也是一種引用地址為了解決函數引用地址不一致的問題,可以使用外部函數:
function Box(name, age) {	this.name = name;	this.age = age;	this.run = run;}function run() {				//通過外面調用,保證引用地址一致	return this.name + this.age + '運行中...';}雖然使用了全局的函數run()來解決了保證引用地址一致的問題,但這種方式又帶來了一個新的問題,全局中的this在對象調用的時候是Box本身,而當作普通函數調用的時候,this又代表window。

原型

我們創建的每個函數都有一個PRototype(原型)屬性,這個屬性是一個對象,它的用途是包含可以由特定類型的所有實例共享的屬性和方法,邏輯上可以這么理解:prototype是通過調用構造函數而創建的原型對象。簡單的說就是靜態屬性和方法。
<script type="text/javascript">	function Box() {};//聲明一個構造函數	Box.prototype.name = 'Lee';//在原型里添加屬性	Box.prototype.age = 100;						Box.prototype.run = function () {//在原型里添加方法		return this.name + this.age + '運行中...';	};	console.log("實例化之前:");	console.log(Box.prototype);	var box1 = new Box();	console.log("實例化之后:");	console.log(Box.prototype);	console.log(Box.prototype == box1.__proto__); //true,證明Box的原型對象在實例化之前就已經存在		var box2 = new Box();	console.log(box1.run == box2.run);//true,方法的引用地址保持一致	</script>運行結果:原型對象中的constructor是一個函數,代表構造函數本身為了更進一步了解構造函數的聲明方式和原型模式的聲明方式,我們通過圖示來了解一下:構造函數模式:原型模式:在原型模式聲明中,多了兩個屬性,這兩個屬性都是創建對象時自動生成的。__proto__屬性是實例指向原型對象的一個指針。
<script type="text/javascript">	function Box() {}					//聲明一個構造函數	Box.prototype.name = 'Lee';				//在原型里添加屬性	Box.prototype.age = 100;						Box.prototype.run = function () {			//在原型里添加方法		return this.name + this.age + '運行中...';	};	var box = new Box();	console.log(box.__proto__);	var obj = new Object();	console.log(obj.__proto__);</script>在瀏覽器里查看打印的結果:可以看到,Box實例對象的__proto__屬性指向的Box構造函數的原型對象,原型對象里的constructor是原型本身,Box構造函數的原型對象默認是繼承自Object。
<script type="text/javascript">	function Box() {}			//聲明一個構造函數	Box.prototype = new Number(2);	var box = new Box();	console.log(box.__proto__);	console.log(box.__proto__.__proto__);	var obj = new Number();	console.log(obj);	console.log(obj.__proto__);</script>查看輸出結果:從結果可以看出,Number的原型對象重寫了toString和valueOf方法,原型對象繼承在Object判斷一個對象是否指向了該構造函數的原型對象,可以使用isPrototypeOf()方法來測試。
alert(Box.prototype.isPrototypeOf(box));isPrototypeOf()函數執行流程:1.先查找構造函數實例里的屬性或方法,如果有,立刻返回;如果構造函數實例里沒有,則去它的原型對象里找,如果有,就返回對象屬性和方法的訪問順序:1.先查找構造函數實例里的屬性或方法,如果有,立刻返回;如果構造函數實例里沒有,則去它的原型對象里找,如果有,就返回;
<script type="text/javascript">	function Box() {};//聲明一個構造函數	Box.prototype.name = 'Lee';//在原型里添加屬性	var box = new Box();	box.name = "li";//li	console.log(box.name);//覆蓋原型中的屬性	delete box.name;//刪除構造函數里的屬性	console.log(box.name);//Lee			</script>hasOwnProperty():判斷對象實例中是否有某個屬性。in操作符:屬性是否存在于實例或者原型中。
<script type="text/javascript">	function Box(){		this.name = "lisong";	}	Box.prototype.age = 26;	function isProperty(object, property) {		//判斷原型中是否存在屬性		return !object.hasOwnProperty(property) && (property in object);	}	var box = new Box();	console.log(isProperty(box, 'name'))		//false	console.log(isProperty(box, 'age'))			//true</script>使用字面量創建原型對象:
<script type="text/javascript">	function Box(){}	console.log(Box.prototype);	Box.prototype = {		age:26,		name:"lisong"	}	console.log(Box.prototype);	var box = new Box();	console.log(box.name);//lisong	console.log(Box.prototype.constructor == Box);//false	console.log(Box.prototype.constructor == Object);//true</script>運行結果:從結果可以看出,用字面量創建的原型對象,其constructor屬性會指向Object的構造函數,而不會指向Box的構造函數

組合構造函數+原型模式

function Box(name, age) {					//不共享的使用構造函數	this.name = name;	this.age = age;	this. family = ['父親', '母親', '妹妹'];};Box.prototype = {						//共享的使用原型模式	constructor : Box,	run : function () {		return this.name + this.age + this.family;	}};這種混合模式很好的解決了傳參和引用共享的大難題。是創建對象比較好的方法

動態原型模式

原型模式,不管你是否調用了原型中的共享方法,它都會初始化原型中的方法,并且在聲明一個對象時,構造函數+原型部分讓人感覺又很怪異,最好就是把構造函數和原型封裝到一起。
function Box(name ,age) {					//將所有信息封裝到函數體內	this.name = name;	this.age = age;		if (typeof this.run != 'function') {			//僅在第一次調用的初始化		Box.prototype.run = function () {			return this.name + this.age + '運行中...';		};	}}var box = new Box('Lee', 100);alert(box.run());

寄生構造函數

寄生構造函數,其實就是工廠模式+構造函數模式。這種模式比較通用,但不能確定對象關系。
function Box(name, age) {	var obj = new Object();	obj.name = name;	obj.age = age;	obj.run = function () {		return this.name + this.age + '運行中...';	};	return obj;}假設要創建一個具有額外方法的引用類型。由于之前說明不建議直接String.prototype.addstring,可以通過寄生構造的方式添加。
function myString(string) {						var str = new String(string);	str.addstring = function () {		return this + ',被添加了!';	};	return str;}var box = new myString('Lee');			//比直接在引用原型添加要繁瑣好多alert(box.addstring());

原型鏈繼承

<script type="text/javascript">	function Box() {					//Box構造		this.name = 'Lee';	}	function Desk() {					//Desk構造		this.age = 100;	}	Desk.prototype = new Box();				//Desc繼承了Box,通過原型,形成鏈條	var desk = new Desk();	console.log(desk.age);	console.log(desk.name);								//得到被繼承的屬性	function Table() {					//Table構造	this.level = 'AAAAA';	}								Table.prototype = new Desk();				//繼續原型鏈繼承	var table = new Table();	console.log(table.name);				//繼承了Box和Desk	console.log(table instanceof Object);			//true	console.log(desk instanceof Table);			//false,desk是table的超類	console.log(table instanceof Desk);			//true	console.log(table instanceof Box);			//true</script>

對象冒充繼承(借用構造函數)

對象冒充繼承主要解決超類型無法傳參的問題
<script type="text/javascript">	function Box(age) {		this.name = ['Lee', 'Jack', 'Hello']		this.age = age;	}	function Desk(age) {		Box.call(this, age);//對象冒充,給超類型傳參	}	var desk = new Desk(200);	console.log(desk.age);	console.log(desk.name);</script>

組合繼承(原型鏈+對象冒充)

借用構造函數雖然解決了剛才兩種問題,但沒有原型,復用則無從談起。所以,我們需要原型鏈+借用構造函數的模式,這種模式成為組合繼承。
<script type="text/javascript">	function Box(age) {		this.name = ['Lee', 'Jack', 'Hello']		this.age = age;	}	Box.prototype.run = function () {						return this.name + this.age;	};	function Desk(age) {		Box.call(this, age);				//對象冒充,第二次調用超類Box	}	Desk.prototype = new Box();				//原型鏈繼承,第一次調用超類Box	var desk = new Desk(100);	console.log(desk.run());	function isPropertyToProto(object, property) {		//判斷原型中是否存在屬性		return !object.hasOwnProperty(property) && (property in object);	}	console.log(isPropertyToProto(desk,"run"));//true	console.log(desk.hasOwnProperty("age"));//true	console.log(desk.__proto__.hasOwnProperty("age"));//true</script>組合繼承缺點:某些屬性在構造函數里和原型對象里都有,重復了,還有即使超類被調用了兩次

原型式繼承

借助原型并基于已有的對象創建新對象,同時還不必因此創建自定義類型。
<script type="text/javascript">	function obj(o) {					//傳遞一個字面量函數		function F() {}					//創建一個構造函數		F.prototype = o;				//把字面量函數賦值給構造函數的原型		return new F();					//最終返回出實例化的構造函數	}	var box = {						//字面量對象		name : 'Lee',		arr : ['哥哥','妹妹','姐姐']	};	var box1 = obj(box);					//傳遞</script>

寄生式繼承(原型式+工廠模式)

原型式+工廠模式結合而來,目的是為了封裝創建對象的過程。
<script type="text/javascript">	function obj(o) {					//傳遞一個字面量函數		function F() {}					//創建一個構造函數		F.prototype = o;				//把字面量函數賦值給構造函數的原型		return new F();					//最終返回出實例化的構造函數	}	var box = {						//字面量對象		name : 'Lee',		arr : ['哥哥','妹妹','姐姐']	};	function create(o) {					//封裝創建過程		var f= obj(o);		f.run = function () {			return this.arr;			//同樣,會共享引用		}; 		return f;	}	var box1 = create(box);	console.log(box1.run());//["哥哥", "妹妹", "姐姐"]</script>上面的代碼主要是為了封裝額外的方法和屬性

寄生組合繼承(寄生+組合)

解決組合繼承超類調用兩次的問題
<script type="text/javascript">      function Box(name) {          this.name = name;          this.arr = ['哥哥','妹妹','父母'];      }      Box.prototype.run = function () {          return this.name;      };      function Desk(name, age) {          Box.call(this, name);//對象冒充          this.age = age;      }      function obj(o) {          function F() {}          F.prototype = o;          return new F();      }      function create(box, desk) {//原型繼承         	var f = obj(box.prototype);          f.constructor = desk;          desk.prototype = f;        /*        desk.prototype = box.prototype;        //會同時修改掉box的constructor,所以不能使用desk.prototype = box.prototype        desk.prototype.constructor = desk;        */    }     create(Box,Desk);      var d = new Desk("lisong",26);      console.log(d.run());//lisong </script>
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲毛片在线观看| 久热精品在线视频| 亚洲图片欧洲图片av| 亚洲娇小xxxx欧美娇小| 欧美国产极速在线| 国产91成人video| 亚洲成人网av| 日韩在线观看免费全集电视剧网站| 国产美女直播视频一区| 亚洲深夜福利网站| 国产成人jvid在线播放| 欧美亚洲视频在线观看| 国产一区二区三区在线视频| 亚洲精品电影网在线观看| 成人国产精品一区二区| 欧美在线视频在线播放完整版免费观看| 欧美中文在线观看国产| 另类图片亚洲另类| 亚洲精品福利视频| 国产精品久久久久av| 日本高清不卡在线| 国产97免费视| 日韩中文字幕国产| 国产美女被下药99| 久久久亚洲国产天美传媒修理工| 亚洲人在线观看| 国产美女扒开尿口久久久| 26uuu久久噜噜噜噜| 国产一区二区三区直播精品电影| 欧美色欧美亚洲高清在线视频| 日韩av日韩在线观看| 日韩在线中文视频| 国产一区二区在线播放| 亚洲精品久久久久久久久久久| 日韩成人中文电影| 国产精品欧美在线| 欧美精品在线视频观看| 欧美在线国产精品| 91国产高清在线| 中文字幕亚洲无线码在线一区| 欧美黄色小视频| 亚洲精品国产精品国自产在线| 欧美日韩国产丝袜另类| 国产精品91久久| 亚洲第一福利在线观看| 日本不卡视频在线播放| 国产精品大陆在线观看| 91欧美视频网站| 91精品视频观看| 成人亚洲综合色就1024| 欧美视频在线免费看| 91午夜在线播放| 91在线无精精品一区二区| 国产精品劲爆视频| 国产精品久久久精品| 国产精品18久久久久久麻辣| 国产视频在线观看一区二区| 在线看日韩欧美| 中文字幕亚洲一区二区三区五十路| 亚洲欧美一区二区精品久久久| 欧美黄色www| 中国日韩欧美久久久久久久久| 91精品视频在线看| 26uuu另类亚洲欧美日本一| 免费99精品国产自在在线| 亚洲第一色中文字幕| 精品久久久999| 97视频在线播放| 97超级碰碰碰| 亚洲无限av看| 日韩一区二区三区在线播放| 日韩女优人人人人射在线视频| 国产精品久久久久久久久粉嫩av| 久久人人爽人人爽人人片亚洲| 国产精品日韩精品| 国产精品户外野外| 97视频国产在线| 狠狠躁18三区二区一区| xxav国产精品美女主播| 欧美日韩国产综合视频在线观看中文| 91精品久久久久久久久中文字幕| 亚洲精品大尺度| 中文字幕av一区二区三区谷原希美| 午夜精品在线视频| 日韩欧美一区二区在线| 精品国产区一区二区三区在线观看| 97在线视频国产| 欧美中文字幕视频在线观看| 成人动漫网站在线观看| 亚洲福利视频网| 国产免费一区二区三区香蕉精| 北条麻妃在线一区二区| 欧美华人在线视频| 最近中文字幕2019免费| 日韩hd视频在线观看| 国产精品美女久久| 麻豆乱码国产一区二区三区| 亚洲精品网站在线播放gif| 精品视频9999| 欧美日韩福利在线观看| 亚洲综合精品伊人久久| 成人性生交大片免费看视频直播| 成人国产在线视频| 亚洲理论片在线观看| 欧美电影免费观看高清完整| 亚洲女在线观看| 97av在线视频| 中文字幕日韩精品有码视频| 9.1国产丝袜在线观看| 日韩精品久久久久久福利| 91免费国产网站| 中文字幕日韩欧美精品在线观看| 久久亚洲精品成人| 精品成人国产在线观看男人呻吟| 国产一区二区三区欧美| 国产精品9999| 91精品久久久久久久久| 97视频在线观看播放| 中文国产成人精品久久一| 97精品一区二区视频在线观看| 色偷偷88888欧美精品久久久| 性亚洲最疯狂xxxx高清| 韩国三级电影久久久久久| 亚洲欧美日韩国产成人| 日韩欧美在线网址| 久久免费视频网| 欧美激情欧美激情在线五月| 中文字幕久热精品在线视频| 国产97在线观看| 日本人成精品视频在线| 久久黄色av网站| 91九色视频导航| 亚州精品天堂中文字幕| 欧美精品videosex极品1| 日韩一区av在线| 国产精品视频久久| 狠狠综合久久av一区二区小说| 欧美亚洲在线观看| 欧美日韩美女视频| 最近2019中文字幕在线高清| 性色av一区二区三区免费| 亚洲成人av在线播放| 中文字幕日韩精品在线观看| 日韩在线免费视频观看| 亚洲精品视频在线播放| 欧美激情一级二级| 国产日韩亚洲欧美| 亚洲精品一区中文字幕乱码| 日韩第一页在线| 国产精品尤物福利片在线观看| 色狠狠久久aa北条麻妃| 欧美激情在线播放| 亚洲午夜精品久久久久久性色| 日本91av在线播放| 国内精品视频一区| 69av成年福利视频| 国产精品男女猛烈高潮激情| 不卡av电影在线观看| 亚洲美女动态图120秒| 国产欧美日韩精品丝袜高跟鞋| 中文字幕视频在线免费欧美日韩综合在线看| 亚洲色图校园春色| 亚洲精品久久久久| 欧美日韩国产区|