javascript
JavaScript高级学习(三)
一. 原型和原型鏈
實(shí)例對(duì)象中的__proto__原型指向的是構(gòu)造函數(shù)中的原型prototype
consolg.log(per.__proto__==Person.prptptype);//true
實(shí)例對(duì)象可以直接訪問(wèn)原型對(duì)象中的屬性或者方法。
原型鏈:實(shí)例對(duì)象和原型對(duì)象之間的關(guān)系,是通過(guò)原型(__proto__)來(lái)聯(lián)系的。
二. 原型指向
原型指向是否可以改變?——可以
構(gòu)造函數(shù)中的this就是實(shí)例對(duì)象
原型對(duì)象的方法中的this就是實(shí)例對(duì)象
1.原型指向的改變:
實(shí)例對(duì)象的原型__proto__指向的是該對(duì)象所在的構(gòu)造函數(shù)的原型對(duì)象prototype,構(gòu)造函數(shù)的的原型對(duì)象prototype指向如果改變了,實(shí)例對(duì)象的原型__proto__之象也會(huì)改變。
stu可以調(diào)用eat(),不可以調(diào)用sayHi()
原型的指向是可以改變的
實(shí)例對(duì)象和原型對(duì)象之間的關(guān)系是通過(guò)__proto__原型來(lái)聯(lián)系起來(lái)的,這個(gè)關(guān)系就是原型鏈。
2.原型的最終指向
實(shí)例對(duì)象中有__proto__原型
構(gòu)造函數(shù)中有prototype原型
prototype是對(duì)象,所以prototype對(duì)象也有__proto__---->指向哪里?
實(shí)例對(duì)象中的__proto__----->構(gòu)造函數(shù)的prototype
所以,prototype這個(gè)對(duì)象的__proto__之鄉(xiāng)的應(yīng)該是某個(gè)構(gòu)造函數(shù)的原型prototype。
以這個(gè)代碼為例:
function Person() {}Person.prototype.eat=function () {console.log("吃東西");};var per=new Person();console.dir(per);console.dir(Person);stu.proto----->Person.prototype
Person.prototype.proto----->Object.prototype
Object.prototype.proto------>null
3.原型指向改變?nèi)绾翁砑臃椒?#xff1f;
原型改變指向有兩種順序:
①先方法后指向
原型指向改變,不再指向含有sayHi()的原型,所以無(wú)法訪問(wèn)sayHi()
②先改指向后添方法
由于先改變指向,再添加方法,所以sayHi()添加到了改變指向后的“實(shí)例對(duì)象”中。
先改變指向后添加方法可以訪問(wèn)到相應(yīng)的方法
4.實(shí)例對(duì)象和原型對(duì)象屬性重名問(wèn)題
function Person(age,sex) {this.age=age;this.sex=sex;}Person.prototype.sex="女";var per=new Person(10,"男");console.log(per.sex);//男實(shí)例對(duì)象訪問(wèn)sex屬性,應(yīng)該先從實(shí)例對(duì)象中找,找到了直接用,找不到的時(shí)候就去指向的原型對(duì)象中找,找到了就使用,找不到…?
console.log(per.fdsfdsfsdfds);//undefined因?yàn)镴S是一門(mén)動(dòng)態(tài)語(yǔ)言,當(dāng)一個(gè)對(duì)象沒(méi)有一個(gè)東西時(shí)時(shí),只要點(diǎn)了,那么這個(gè)對(duì)象就有了這個(gè)東西;當(dāng)沒(méi)有這個(gè)屬性時(shí),只要對(duì)象.屬性名字,對(duì)象就有這個(gè)屬性了,但是,該屬性沒(méi)有賦值,所以,結(jié)果是:undefined
console.log(fsdfdsfds);//報(bào)錯(cuò)沒(méi)有fsdfdsfds這么變量
5.一個(gè)指向的例子
<div id="dv"></div> <script>var divObj=document.getElementById("dv");console.dir(divObj);</script>我們可以看到div的結(jié)構(gòu),然后查看他的指向
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
繼承
面向?qū)ο缶幊趟枷?#xff1a;
??????根據(jù)需求,分析對(duì)象,找到對(duì)象的特征和行為,通過(guò)代碼的形式實(shí)現(xiàn)需求,要想實(shí)現(xiàn)需求,就要?jiǎng)?chuàng)建對(duì)象:構(gòu)造函數(shù)------創(chuàng)建對(duì)象,通過(guò)調(diào)用屬性和方法來(lái)實(shí)現(xiàn)相應(yīng)的功能及需求。
JS不是面向?qū)ο笳Z(yǔ)言,而是基于對(duì)象的語(yǔ)言。-------為什么學(xué)習(xí)面向?qū)ο?#xff1f;
??????面向?qū)ο笏枷敫m合人的思想,編程起來(lái)更加的方便,及后期的維護(hù)。
面向?qū)ο蟮奶卣?#xff1a;
- 封裝:就是包裝
一個(gè)值存儲(chǔ)再一個(gè)變量中------封裝
一段重復(fù)代碼放在一個(gè)函數(shù)中-------封裝
… - 多態(tài)
一個(gè)對(duì)象有不同的行為,或者是同一個(gè)行為針對(duì)不同的對(duì)象,產(chǎn)生不同的結(jié)果
要想有多態(tài),就要有繼承,JS可以模擬多態(tài),但是不會(huì)使用 - 繼承
是一種關(guān)系,類與類之間的關(guān)系,JS通過(guò)構(gòu)造函數(shù)模擬類,通過(guò)原型實(shí)現(xiàn)繼承
繼承是為了多態(tài)服務(wù),JS的繼承也是為了實(shí)現(xiàn)數(shù)據(jù)共享。
原型的作用:
- 數(shù)據(jù)共享,節(jié)省內(nèi)存空間
- 為了實(shí)現(xiàn)繼承
繼承是一種關(guān)系,父類級(jí)別和類級(jí)別的關(guān)系。
1.改變?cè)椭赶?#xff1a;
Student.prototype=new Person("小明“,10,"男");例子:
//動(dòng)物的構(gòu)造韓素function Animal(name,weight) {this.name=name;this.weight=weight;}//動(dòng)物的原型的方法Animal.prototype.eat=function () {console.log("天天吃東西,就是吃");};//狗的構(gòu)造函數(shù)function Dog(color) {this.color=color;}Dog.prototype=new Animal("哮天犬","50kg");Dog.prototype.bitePerson=function () {console.log("哼~汪汪~(yú)咬死你");};//哈士奇function ErHa(sex) {this.sex=sex;}ErHa.prototype=new Dog("黑白色");ErHa.prototype.playHost=function () {console.log("哈哈~要壞衣服,要壞桌子,拆家..嘎嘎...好玩,開(kāi)心不,驚喜不,意外不");};var erHa=new ErHa("雄性");console.log(erHa.name,erHa.weight,erHa.color);erHa.eat();erHa.bitePerson();erHa.playHost();
2.借用構(gòu)造函數(shù)
我們來(lái)看下下面的例子
function Person(name,age,sex,weight) {this.name=name;this.age=age;this.sex=sex;this.weight=weight;}Person.prototype.sayHi=function () {console.log("您好");};function Student(score) {this.score=score;}//希望人的類別中的數(shù)據(jù)可以共享給學(xué)生---繼承Student.prototype=new Person("小明",10,"男","50kg");var stu1=new Student("100");console.log(stu1.name,stu1.age,stu1.sex,stu1.weight,stu1.score);stu1.sayHi();以上代碼實(shí)現(xiàn)了繼承,實(shí)例對(duì)象stu1繼承了Person的屬性和方法,但是,之后創(chuàng)建的所有實(shí)例對(duì)象的屬性值都是一樣的
為了數(shù)據(jù)共享,改變?cè)椭赶?#xff0c;做到了繼承
①缺陷:因?yàn)楦淖冊(cè)椭赶虻耐瑫r(shí)實(shí)現(xiàn)了繼承,直接初始化了屬性,繼承過(guò)來(lái)的屬性值都是一樣的--------問(wèn)題
重新調(diào)用對(duì)象的屬性進(jìn)行賦值可以解決這個(gè)問(wèn)題,但是這樣會(huì)增加代碼,太過(guò)繁瑣。
②解決方案:繼承的時(shí)候,不用改變?cè)偷闹赶?#xff0c;直接調(diào)用父級(jí)的構(gòu)造函數(shù)的方式來(lái)為屬性賦值--------借用構(gòu)造函數(shù)(把要繼承的父級(jí)的構(gòu)造函數(shù)拿出來(lái),使用一下)
function Person(name, age, sex, weight) {this.name = name;this.age = age;this.sex = sex;this.weight = weight;}Person.prototype.sayHi = function () {console.log("您好");};function Student(name,age,sex,weight,score) {//借用構(gòu)造函數(shù)Person.call(this,name,age,sex,weight);this.score = score;}var stu1 = new Student("小明",10,"男","10kg","100");console.log(stu1.name, stu1.age, stu1.sex, stu1.weight, stu1.score);var stu2 = new Student("小紅",20,"女","20kg","120");console.log(stu2.name, stu2.age, stu2.sex, stu2.weight, stu2.score);var stu3 = new Student("小麗",30,"妖","30kg","130");console.log(stu3.name, stu3.age, stu3.sex, stu3.weight, stu3.score);
借用構(gòu)造函數(shù):
- 構(gòu)造函數(shù)名字.call(當(dāng)前對(duì)象,屬性1,屬性2…)
- 解決屬性繼承,并且值不重復(fù)的問(wèn)題;
- 缺陷:父級(jí)類別中的方法不能繼承。
3.組合繼承
為了解決借用構(gòu)造函數(shù)實(shí)現(xiàn)繼承所帶來(lái)的問(wèn)題(父級(jí)類別中的方法不能繼承),我們采用組合繼承來(lái)實(shí)現(xiàn)繼承---------原型繼承+借用構(gòu)造函數(shù)繼承。
4.拷貝繼承
拷貝繼承:把一個(gè)對(duì)象中的屬性或者方法直接復(fù)制到另一個(gè)對(duì)象中
5.繼承的總結(jié)
- 面向?qū)ο蟮奶匦?#xff1a;封裝、繼承、多態(tài)
- 繼承:類與類之間的關(guān)系,面向?qū)ο笳Z(yǔ)言的繼承是為了多態(tài)服務(wù)的。JS不是面向?qū)ο笳Z(yǔ)言,但是可以模擬面向?qū)ο?#xff0c;模擬繼承,為了節(jié)省空間。
- 繼承
①原型作用:數(shù)據(jù)共享;目的:節(jié)省空間
??????????????????????繼承;目的:節(jié)省空間
②原型繼承:改變?cè)椭赶?br /> ③借用構(gòu)造函數(shù)繼承:主要解決屬性值相同的問(wèn)題(Person.call(this,name,age))
④組合繼承:原型繼承+借用構(gòu)造函數(shù)繼承
??????????????????????既能解決屬性值相等的問(wèn)題,又能解決父級(jí)方法調(diào)用問(wèn)題
⑤拷貝繼承:就是把對(duì)象中需要共享的屬性或者方法,直接遍歷的方式復(fù)制
??????????????????????到另一個(gè)對(duì)象中
其他知識(shí)點(diǎn)
1.逆推繼承看原型
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
f3.age先在實(shí)例對(duì)象中查找,若找不到,則逐級(jí)向上查找(原型中),假若原型中也沒(méi)有,為undefined
2.函數(shù)角色
函數(shù)角色:函數(shù)聲明、函數(shù)表達(dá)式
- 函數(shù)聲明
- 函數(shù)表達(dá)式
- 函數(shù)聲明和函數(shù)表達(dá)式的區(qū)別
函數(shù)聲明如果放在if-else語(yǔ)句中,在IE8的瀏覽器中會(huì)出現(xiàn)問(wèn)題;函數(shù)表達(dá)式則不會(huì)出現(xiàn)問(wèn)題。
3.函數(shù)中this指向問(wèn)題
- 普通函數(shù)中的this-------window
- 對(duì)象方法中的this-------當(dāng)前的實(shí)例對(duì)象
- 定時(shí)器方法中的this-------window
- 構(gòu)造函數(shù)中的this-------實(shí)例對(duì)象
- 原型對(duì)象中的this--------實(shí)例對(duì)象
4.嚴(yán)格模式
嚴(yán)格模式下,方法應(yīng)由對(duì)象調(diào)用
5.函數(shù)的不同調(diào)用方法
- 普通函數(shù)
- 構(gòu)造函數(shù)
- 對(duì)象的方法
6.函數(shù)也是對(duì)象,對(duì)象不一定是函數(shù)
對(duì)象中有__proto__原型,是對(duì)象
函數(shù)中有prototype原型,是對(duì)象
對(duì)象中有__proto__,函數(shù)中應(yīng)該有prototype
如果一個(gè)東西里面有prototype,又有__proto__,說(shuō)明是函數(shù),也是對(duì)象
所有的函數(shù)實(shí)際上都是Function的構(gòu)造函數(shù)創(chuàng)建出來(lái)的實(shí)例對(duì)象====>函數(shù)也是對(duì)象
Math中有__proto__,但是沒(méi)有prorotype,所以Math是對(duì)象,但不是函數(shù)====>對(duì)象不一定是函數(shù)
7.數(shù)組中的函數(shù)調(diào)用
數(shù)組可以存儲(chǔ)任何類型的數(shù)據(jù)
var arr=[function () {console.log("十一假期快樂(lè)");},function () {console.log("十一假期開(kāi)心");},function () {console.log("十一假期健康");},function () {console.log("十一假期安全");},function () {console.log("十一假期如意");}];//回調(diào)函數(shù):函數(shù)作為參數(shù)使用arr.forEach(function(ele){ele();});forEach() 方法用于調(diào)用數(shù)組的每個(gè)元素,并將元素傳遞給回調(diào)函數(shù)。
注意: forEach() 對(duì)于空數(shù)組是不會(huì)執(zhí)行回調(diào)函數(shù)的。
array.forEach(function(currentValue, index, arr), thisValue)
總結(jié)
以上是生活随笔為你收集整理的JavaScript高级学习(三)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【P3369 普通平衡树】 Splay
- 下一篇: gradle idea java ssm