国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 網(wǎng)站 > WEB開(kāi)發(fā) > 正文

javascript筆記--(第十五章)面向?qū)ο笈c原型

2024-04-27 15:05:00
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

面向?qū)ο?/h1>ECMAScript有兩種開(kāi)發(fā)模式:1.函數(shù)式(過(guò)程化),2.面向?qū)ο?OOP)。面向?qū)ο蟮恼Z(yǔ)言有一個(gè)標(biāo)志,那就是類(lèi)的概念,而通過(guò)類(lèi)可以創(chuàng)建任意多個(gè)具有相同屬性和方法的對(duì)象。但是,ECMAScript沒(méi)有類(lèi)的概念,因此它的對(duì)象也與基于類(lèi)的語(yǔ)言中的對(duì)象有所不同。

工廠方法

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

構(gòu)造函數(shù)

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

原型

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

組合構(gòu)造函數(shù)+原型模式

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

動(dòng)態(tài)原型模式

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

寄生構(gòu)造函數(shù)

寄生構(gòu)造函數(shù),其實(shí)就是工廠模式+構(gòu)造函數(shù)模式。這種模式比較通用,但不能確定對(duì)象關(guān)系。
function Box(name, age) {	var obj = new Object();	obj.name = name;	obj.age = age;	obj.run = function () {		return this.name + this.age + '運(yùn)行中...';	};	return obj;}假設(shè)要?jiǎng)?chuàng)建一個(gè)具有額外方法的引用類(lèi)型。由于之前說(shuō)明不建議直接String.prototype.addstring,可以通過(guò)寄生構(gòu)造的方式添加。
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構(gòu)造		this.name = 'Lee';	}	function Desk() {					//Desk構(gòu)造		this.age = 100;	}	Desk.prototype = new Box();				//Desc繼承了Box,通過(guò)原型,形成鏈條	var desk = new Desk();	console.log(desk.age);	console.log(desk.name);								//得到被繼承的屬性	function Table() {					//Table構(gòu)造	this.level = 'AAAAA';	}								Table.prototype = new Desk();				//繼續(xù)原型鏈繼承	var table = new Table();	console.log(table.name);				//繼承了Box和Desk	console.log(table instanceof Object);			//true	console.log(desk instanceof Table);			//false,desk是table的超類(lèi)	console.log(table instanceof Desk);			//true	console.log(table instanceof Box);			//true</script>

對(duì)象冒充繼承(借用構(gòu)造函數(shù))

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

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

借用構(gòu)造函數(shù)雖然解決了剛才兩種問(wèn)題,但沒(méi)有原型,復(fù)用則無(wú)從談起。所以,我們需要原型鏈+借用構(gòu)造函數(shù)的模式,這種模式成為組合繼承。
<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);				//對(duì)象冒充,第二次調(diào)用超類(lèi)Box	}	Desk.prototype = new Box();				//原型鏈繼承,第一次調(diào)用超類(lèi)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>組合繼承缺點(diǎn):某些屬性在構(gòu)造函數(shù)里和原型對(duì)象里都有,重復(fù)了,還有即使超類(lèi)被調(diào)用了兩次

原型式繼承

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

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

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

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

解決組合繼承超類(lèi)調(diào)用兩次的問(wèn)題
<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);//對(duì)象冒充          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;        //會(huì)同時(shí)修改掉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>
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 荆门市| 西乡县| 溧水县| 津市市| 宁海县| 定南县| 科尔| 雷州市| 甘谷县| 大港区| 赤峰市| 吉首市| 阜南县| 延边| 淮南市| 西宁市| 宝应县| 南澳县| 石门县| 博兴县| 武鸣县| 连州市| 梁山县| 定西市| 三原县| 喀什市| 汉源县| 金川县| 富裕县| 宣武区| 石景山区| 雅安市| 穆棱市| 自贡市| 金坛市| 罗定市| 栾川县| 砀山县| 崇礼县| 玉屏| 剑川县|