javascript
JavaScript学习记录十六
原型鏈的引入
??? //如果想要使用一些屬性和方法,并且屬性的值在每個(gè)對(duì)象中都是一樣的,方法在每個(gè)對(duì)象中的操作也都是一樣,
??? //那么,為了共享數(shù)據(jù),節(jié)省內(nèi)存空間,是可以把屬性和方法通過(guò)原型的方式進(jìn)行賦值
??? //實(shí)例對(duì)象的原型__proto__和構(gòu)造函數(shù)的原型prototype指向是相同的
??? //實(shí)例對(duì)象中的__proto__原型指向的是構(gòu)造函數(shù)中的原型prototype
??? //實(shí)例對(duì)象中__proto__是原型,瀏覽器使用的
??? //構(gòu)造函數(shù)中的prototype是原型,程序員使用的
??? //原型鏈:是一種關(guān)系,實(shí)例對(duì)象和原型對(duì)象之間的關(guān)系,關(guān)系是通過(guò)原型(__proto__)來(lái)聯(lián)系的
console.log(per.__proto__==Person.prototype); true??? //構(gòu)造函數(shù)中的this就是實(shí)例對(duì)象
??? //原型對(duì)象中方法中的this就是實(shí)例對(duì)象
??? ↓三處的打印是相同的
<script>function Person(age) {this.age=age;console.log(this);}Person.prototype.eat=function () {console.log(this);};var per=new Person(10);console.log(per); </script>__proto__指向分析
??? //實(shí)例對(duì)象中有__proto__原型
??? //構(gòu)造函數(shù)中有prototype原型
??? //prototype是對(duì)象
??? //所以,prototype這個(gè)對(duì)象中也有__proto__,那么指向了哪里
??? //實(shí)例對(duì)象中的__proto__指向的是構(gòu)造函數(shù)的prototype
??? //所以,prototype這個(gè)對(duì)象中__proto__指向的應(yīng)該是某個(gè)構(gòu)造函數(shù)的原型prototype
??? //per實(shí)例對(duì)象的__proto__------->Person.prototype的__proto__---->Object.prototype的__proto__是null
<script>function Person(age) {this.age=age;}var per=new Person(10);console.log(Person.prototype.__proto__==Object.prototype);//trueconsole.log(Object.prototype.__proto__); null </script>原型的指向改變,添加原型方法需要在原型改變之后
function Person(age) {this.age = age;}指向改變了Person.prototype = {eat: function () {console.log("吃");}};先添加原型方法Person.prototype.sayHi = function () {console.log("您好");};var per = new Person(10);per.sayHi();</script>實(shí)例對(duì)象和原型對(duì)象的屬性分析
??? //因?yàn)镴S是一門動(dòng)態(tài)類型的語(yǔ)言,對(duì)象沒(méi)有什么,只要點(diǎn)了,那么這個(gè)對(duì)象就有了這個(gè)東西,沒(méi)有這個(gè)屬性,只要對(duì)象.屬性名字,對(duì)象就有這個(gè)屬性了,但是,該屬性沒(méi)有賦值,所以,結(jié)果是:undefined
????? console.log(per.fdsfdsfsdfds);? undefined
??? //實(shí)例對(duì)象訪問(wèn)這個(gè)屬性,應(yīng)該先從實(shí)例對(duì)象中找,找到了就直接用,找不到就去指向的原型對(duì)象中找,找到了就使用,找不到呢?=====
??? //通過(guò)實(shí)例對(duì)象能否改變?cè)蛯?duì)象中的屬性值?不能
??? //就想改變?cè)蛯?duì)象中屬性的值,怎么辦?直接通過(guò)原型對(duì)象.屬性=值;可以改變
有趣的原型鏈
??? //原型鏈:實(shí)例對(duì)象和原型對(duì)象之間的關(guān)系,通過(guò)__proto__來(lái)聯(lián)系
? ↓ 以下是普通的div標(biāo)簽的原型鏈指向
??? divObj.__proto__---->HTMLDivElement.prototype的__proto__
??? --->HTMLElement.prototype的__proto__---->Element.prototype的__proto__
??? ---->Node.prototype的__proto__---->EventTarget.prototype的__proto__
??? ---->Object.prototype沒(méi)有__proto__,所以,Object.prototype中的__proto__是null
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>title</title><script>原型鏈:實(shí)例對(duì)象和原型對(duì)象之間的關(guān)系,通過(guò)__proto__來(lái)聯(lián)系</script> </head> <body> <div id="dv"></div> <script>var divObj=document.getElementById("dv");console.dir(divObj); </script> </body> </html>繼承
??? * 面向?qū)ο缶幊趟枷?根據(jù)需求,分析對(duì)象,找到對(duì)象有什么特征和行為,通過(guò)代碼的方式來(lái)實(shí)現(xiàn)需求,要想實(shí)現(xiàn)這個(gè)需求,就要?jiǎng)?chuàng)建對(duì)象,要 想創(chuàng)建對(duì)象,就應(yīng)該顯示有構(gòu)造函數(shù),然后通過(guò)構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象.,通過(guò)對(duì)象調(diào)用屬性和方法來(lái)實(shí)現(xiàn)相應(yīng)的功能及需求,即可
??? * 首先JS不是一門面向?qū)ο蟮恼Z(yǔ)言,JS是一門基于對(duì)象的語(yǔ)言,那么為什么學(xué)習(xí)js還要學(xué)習(xí)面向?qū)ο?因?yàn)槊嫦驅(qū)ο蟮乃枷脒m合于人的想法,編程起來(lái)會(huì)更加的方便,及后期的維護(hù)....
??? * 面向?qū)ο蟮木幊陶Z(yǔ)言中有類(class)的概念(也是一種特殊的數(shù)據(jù)類型),但是JS不是面向?qū)ο蟮恼Z(yǔ)言,所以,JS中沒(méi)有類(class),但是JS可以模擬面向?qū)ο蟮乃枷刖幊?JS中會(huì)通過(guò)構(gòu)造函數(shù)來(lái)模擬類的概念(class)
??? * 共同的特征和行為
??? * 特征--->屬性
??? * 行為---方法
??? *
??? * 面向?qū)ο蟮奶匦?封裝,繼承,多態(tài)
??? *
??? * 封裝:就是包裝
??? * 一個(gè)值存儲(chǔ)在一個(gè)變量中--封裝
??? * 一坨重復(fù)代碼放在一個(gè)函數(shù)中--封裝
??? * 一系列的屬性放在一個(gè)對(duì)象中--封裝
??? * 一些功能類似的函數(shù)(方法)放在一個(gè)對(duì)象中--封裝
??? * 好多相類似的對(duì)象放在一個(gè)js文件中---封裝
??? *
??? * 繼承: 首先繼承是一種關(guān)系,類(class)與類之間的關(guān)系,JS中沒(méi)有類,但是可以通過(guò)構(gòu)造函數(shù)模擬類,然后通過(guò)原型來(lái)實(shí)現(xiàn)繼承
??? * 繼承也是為了數(shù)據(jù)共享,js中的繼承也是為了實(shí)現(xiàn)數(shù)據(jù)共享
??? *
??? * 原型作用之一:數(shù)據(jù)共享,節(jié)省內(nèi)存空間
??? * 原型作用之二:為了實(shí)現(xiàn)繼承
??? * 多態(tài):一個(gè)對(duì)象有不同的行為,或者是同一個(gè)行為針對(duì)不同的對(duì)象,產(chǎn)生不同的結(jié)果,要想有多態(tài),就要先有繼承,js中可以模擬多態(tài),但是不會(huì)去使用,也不會(huì)模擬,
實(shí)現(xiàn)繼承 function Person(name,age,sex) {this.name=name;this.sex=sex;this.age=age;}Person.prototype.eat=function () {console.log("人可以吃東西");};Person.prototype.sleep=function () {console.log("人在睡覺(jué)");};Person.prototype.play=function () {console.log("生活就是不一樣的玩法而已");};function Student(score) {this.score=score;}Student.prototype=new Person("小明",10,"男");Student.prototype.study=function () {console.log("學(xué)習(xí)很累很累的哦.");};//相同的代碼太多,造成了代碼的冗余(重復(fù)的代碼)var stu=new Student(100);console.log(stu.name);console.log(stu.age);console.log(stu.sex);stu.eat();stu.play();stu.sleep();console.log("下面的是學(xué)生對(duì)象中自己有的");console.log(stu.score);stu.study();借用構(gòu)造函數(shù)
??? //為了數(shù)據(jù)共享,改變?cè)椭赶?做到了繼承---通過(guò)改變?cè)椭赶驅(qū)崿F(xiàn)的繼承
??? //缺陷:因?yàn)楦淖冊(cè)椭赶虻耐瑫r(shí)實(shí)現(xiàn)繼承,直接初始化了屬性,繼承過(guò)來(lái)的屬性的值都是一樣的了,所以,這就是問(wèn)題
??? //解決方案:繼承的時(shí)候,不用改變?cè)偷闹赶?直接調(diào)用父級(jí)的構(gòu)造函數(shù)的方式來(lái)為屬性賦值就可以了------借用構(gòu)造函數(shù):把要繼承的父級(jí)的構(gòu)造函數(shù)拿過(guò)來(lái),使用一下就可以了
??? //借用構(gòu)造函數(shù):構(gòu)造函數(shù)名字.call(當(dāng)前對(duì)象,屬性,屬性,屬性....);
??? //解決了屬性繼承,并且值不重復(fù)的問(wèn)題
??? //缺陷:父級(jí)類別中的方法不能繼承
組合繼承
//原型實(shí)現(xiàn)繼承 //借用構(gòu)造函數(shù)實(shí)現(xiàn)繼承 //組合繼承:原型繼承+借用構(gòu)造函數(shù)繼承 function Person(name,age,sex) {this.name=name;this.age=age;this.sex=sex;}Person.prototype.sayHi=function () {console.log("阿涅哈斯誒呦");};function Student(name,age,sex,score) {借用構(gòu)造函數(shù):屬性值重復(fù)的問(wèn)題Person.call(this,name,age,sex);this.score=score;}改變?cè)椭赶?---繼承Student.prototype=new Person();//不傳值Student.prototype.eat=function () {console.log("吃東西");};var stu=new Student("小黑",20,"男","100分");console.log(stu.name,stu.age,stu.sex,stu.score);小黑 20 男 100分stu.sayHi();阿涅哈斯誒呦stu.eat();吃東西拷貝繼承
var p={name:'wutong',age:12};var p1={};for(var key in p){p1[key]=p[key];}console.dir(p1);console.log(p==p1);//falsefunction Person() {}Person.prototype.name='zhangsan';Person.prototype.age=12;var p2=new Person();for(var key in Person.prototype){p2[key]=Person.prototype[key];}console.dir(p2)繼承總結(jié)
??? //繼承,類與類之間的關(guān)系,面向?qū)ο蟮恼Z(yǔ)言的繼承是為了多態(tài)服務(wù)的,
??? //js不是面向?qū)ο蟮恼Z(yǔ)言,但是可以模擬面向?qū)ο?模擬繼承.為了節(jié)省內(nèi)存空間
??? //繼承:
??? /*
??? * 原型作用: 數(shù)據(jù)共享 ,目的是:為了節(jié)省內(nèi)存空間,
??? * 原型作用: 繼承? 目的是:為了節(jié)省內(nèi)存空間
??? *
??? * 原型繼承:改變?cè)偷闹赶?br /> ??? * 借用構(gòu)造函數(shù)繼承:主要解決屬性的問(wèn)題
??? * 組合繼承:原型繼承+借用構(gòu)造函數(shù)繼承
??? * 既能解決屬性問(wèn)題,又能解決方法問(wèn)題
??? * 拷貝繼承:就是把對(duì)象中需要共享的屬性或者犯法,直接遍歷的方式復(fù)制到另一個(gè)對(duì)象中
逆序繼承看原型
???? *理解:通過(guò)原型實(shí)現(xiàn)了繼承,所以子初始化的時(shí)候必須調(diào)用改變的原型指向的初始化。
???? *f3? age=30? → f3.__proto__.age=20 (f1)? →? f1.__proto__.age=10;
function F1(age) {this.age = age;}function F2(age) {this.age = age;}F2.prototype = new F1(10);function F3(age) {this.age = age;}F3.prototype = new F2(20);var f3 = new F3(30);console.log(f3.age); 30函數(shù)的聲明和函數(shù)表達(dá)式
函數(shù)的聲明function f1() {console.log("我是函數(shù)");}f1();函數(shù)表達(dá)式var ff=function () {console.log("我也是一個(gè)函數(shù)");};ff();函數(shù)聲明和函數(shù)表達(dá)式的區(qū)別
??? //函數(shù)聲明如果放在if-else的語(yǔ)句中,在IE8的瀏覽器中會(huì)出現(xiàn)問(wèn)題,函數(shù)聲明在if-else塊中,塊外無(wú)法實(shí)現(xiàn)調(diào)用
??? //以后寧愿用函數(shù)表達(dá)式,都不用函數(shù)聲明
?
if(true){function f1() {console.log("哈哈,我又變帥了");}}else{function f1() {console.log("小蘇好猥瑣");}}f1();var ff;if(true){ff=function () {console.log("哈哈,我又變帥了");};}else{ff=function () {console.log("小蘇好猥瑣");};}ff();函數(shù)中的this的指向
???? * 普通函數(shù)中的this是誰(shuí)?-----window
???? * 對(duì)象.方法中的this是誰(shuí)?----當(dāng)前的實(shí)例對(duì)象
???? * 定時(shí)器方法中的this是誰(shuí)?----window
???? * 構(gòu)造函數(shù)中的this是誰(shuí)?-----實(shí)例對(duì)象
???? * 原型對(duì)象方法中的this是誰(shuí)?---實(shí)例對(duì)象
普通函數(shù)和構(gòu)造函數(shù)
?? *語(yǔ)法上只有大小寫的區(qū)分,使用上構(gòu)造函數(shù)通過(guò)new來(lái)實(shí)現(xiàn)調(diào)用,普通函數(shù)直接調(diào)用即可
普通函數(shù)function f1() {console.log("文能提筆控蘿莉");}f1();構(gòu)造函數(shù)---通過(guò)new 來(lái)調(diào)用,創(chuàng)建對(duì)象function F1() {console.log("我是構(gòu)造函數(shù),我驕傲");}var f=new F1();區(qū)分函數(shù)和對(duì)象
??? //函數(shù)是對(duì)象,對(duì)象不一定是函數(shù)
??? //對(duì)象中有__proto__原型,是對(duì)象
??? //函數(shù)中有prototype原型,是對(duì)象
?? //如果一個(gè)東西里面有prototype,又有__proto__,說(shuō)明是函數(shù),也是對(duì)象
對(duì)象中有__proto__,函數(shù)中應(yīng)該有prototypeconsole.dir(Math); 中有__proto__,但是沒(méi)有prorotype數(shù)組中函數(shù)的調(diào)用
?? *javascript是弱類型語(yǔ)言,所以數(shù)組中可以存放各種數(shù)據(jù)類型,但是為了方便遍歷,盡量存放同種類型
<script>var arr=[function () {console.log('hello world!')},function () {console.log('hello world!')}];arr.forEach(function (ele) {ele();})</script>?
總結(jié)
以上是生活随笔為你收集整理的JavaScript学习记录十六的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: php创建数组填充数组的方法
- 下一篇: 常用App URL Scheme