JavaScript面向?qū)ο蠛诵闹R(shí)與概念歸納整理
本文實(shí)例講述了JavaScript面向?qū)ο蠛诵闹R(shí)與概念。分享給大家供大家參考,具體如下:
一、面向?qū)ο?/h2>
1.1 概念
- 面向?qū)ο缶褪鞘褂脤?duì)象。面向?qū)ο箝_(kāi)發(fā)就是使用對(duì)象開(kāi)發(fā)。
- 面向過(guò)程就是用過(guò)程的方式進(jìn)行開(kāi)發(fā)。面向?qū)ο笫菍?duì)面向過(guò)程的封裝。
1.2 三大特性
抽象性
所謂的抽象性就是:如果需要一個(gè)對(duì)象描述數(shù)據(jù),需要抽取這個(gè)對(duì)象的核心數(shù)據(jù)
- 提出需要的核心屬性和方法
- 不在特定的環(huán)境下無(wú)法明確對(duì)象的具體意義
封裝性
對(duì)象是將數(shù)據(jù)與功能組合到一起,即封裝
- JS對(duì)象就是鍵值對(duì)的集合,鍵值如果是數(shù)據(jù)(基本數(shù)據(jù)、符合數(shù)據(jù)、空數(shù)據(jù))就稱為屬性,如果鍵值是函數(shù)那么就稱為方法
- 對(duì)象就是將屬性與方法封裝起來(lái)
- 方法是將過(guò)程封裝起來(lái)
繼承性
所謂繼承性就是自己沒(méi)有但是別人有,拿過(guò)來(lái)成為自己的,就是繼承,繼承是實(shí)現(xiàn)復(fù)用的一種手段
- 在Java等語(yǔ)言中繼承滿足一個(gè)class的規(guī)則,類是一個(gè)class,他規(guī)定了一個(gè)對(duì)象有什么屬性和方法。
- 在這些語(yǔ)言中繼承是class之間的繼承,一個(gè)class繼承另一個(gè)class,那么該class就有了另一個(gè)class的成員,那么由該class創(chuàng)建出來(lái)的對(duì)象就同時(shí)具有兩個(gè)class的成員。
在JS中沒(méi)有明確的繼承語(yǔ)法(ES6提供了class extend語(yǔ)法),一般都是按照繼承的理念實(shí)現(xiàn)對(duì)象的成員擴(kuò)充實(shí)現(xiàn)繼承,因此JS中實(shí)現(xiàn)繼承的方法非常對(duì)多。
傳統(tǒng)繼承基于類,JS繼承基于對(duì)象
一個(gè)簡(jiǎn)單的繼承模式:混入(mix)
function mix ( o1, o2 ) { for ( var k in o2 ) { o1[ k ] = o2[ k ]; } }
1.3 關(guān)于面向?qū)ο蟮囊恍┢渌拍?/h3>
類class:在JS中就是構(gòu)造函數(shù)
- 在傳統(tǒng)的面向?qū)ο笳Z(yǔ)言中,使用一個(gè)叫類的東西定義模板,然后使用模板創(chuàng)建對(duì)象。
- 在構(gòu)造方法中也具有類似的功能,因此也稱其為類
實(shí)例(instance)與對(duì)象(object)
- 實(shí)例一般是指某一個(gè)構(gòu)造函數(shù)創(chuàng)建出來(lái)的對(duì)象,我們稱為XXXX 構(gòu)造函數(shù)的實(shí)例
- 實(shí)例就是對(duì)象。對(duì)象是一個(gè)泛稱
- 實(shí)例與對(duì)象是一個(gè)近義詞
鍵值對(duì)與屬性和方法
- 在JS中鍵值對(duì)的集合稱為對(duì)象
- 如果值為數(shù)據(jù)(非函數(shù)),就稱該鍵值對(duì)為屬性
- 如果值為函數(shù)(方法),就稱該鍵值對(duì)為方法method
父類與子類(基類和派生類)
- 傳統(tǒng)的面向?qū)ο笳Z(yǔ)言中使用類來(lái)實(shí)現(xiàn)繼承那么就有父類、子類的概念
- 父類又稱為基類,子類又稱為派生類
- 在JS中沒(méi)有類的概念,在JS中常常稱為父對(duì)象,子對(duì)象,基對(duì)象,派生對(duì)象。
二、構(gòu)造函數(shù)
2.1 構(gòu)造函數(shù)是干什么用的
- 初始化數(shù)據(jù)的
- 在JS中給對(duì)象添加屬性用的,初始化屬性值用的
2.2 創(chuàng)建對(duì)象的過(guò)程
- 代碼:
var p = new Person();
-
首先運(yùn)算符
new
創(chuàng)建了一個(gè)對(duì)象,類似于{}
,是一個(gè)沒(méi)有任何(自定義)成員的對(duì)象。- 使用
new
創(chuàng)建對(duì)象,那么對(duì)象的類型就是創(chuàng)建他的構(gòu)造函數(shù)名 - 使用
{}
無(wú)論如何都是Object類型,相當(dāng)于new Object
- 使用
-
然后調(diào)用構(gòu)造函數(shù),為其初始化成員
- 構(gòu)造函數(shù)在調(diào)用的一開(kāi)始,有一個(gè)賦值操作,即this = 剛剛創(chuàng)建出來(lái)的對(duì)象。
- 因此在構(gòu)造函數(shù)中this表示剛剛創(chuàng)建出來(lái)的對(duì)象。
- 在構(gòu)造函數(shù)中 利用 對(duì)象的動(dòng)態(tài)特性 為其對(duì)象添加成員。
三、作用域
3.1 什么是作用域
域表示的就是范圍,即作用域,就是一個(gè)名字在什么地方可以使用,什么時(shí)候不能使用。
簡(jiǎn)單的說(shuō),作用域是針對(duì)變量的,比如我們創(chuàng)建一個(gè)函數(shù) a1
,函數(shù)里面又包了一個(gè)子函數(shù) a2
。
// 全局作用域 functiona a1() { // a1作用域 function a2() { // a2作用域 } }
此時(shí)就存 在三個(gè)作用域:全局作用域,a1
作用域,a2
作用域;即全局作用域包含了 a1
的作用域,a2
的作用域包含了 a1
的作用域。
當(dāng) a2
在查找變量的時(shí)候會(huì)先從自身的作用域區(qū)查找,找不到再到上一級(jí) a1
的作用域查找,如果還沒(méi)找到就
到全局作用域區(qū)查找,這樣就形成了一個(gè)作用域鏈
。
3.2 JS中詞法作用域的規(guī)則
- 函數(shù)允許訪問(wèn)函數(shù)外部的數(shù)據(jù)
- 整個(gè)代碼結(jié)構(gòu)中只有函數(shù)可以限定作用域
- 作用規(guī)則首先使用提升規(guī)則分析
- 如果當(dāng)前作用域中有了名字了,就不考慮外面的名字
3.3 屬性搜索原則
- 所謂的屬性搜索原則,就是對(duì)象在訪問(wèn)屬性或方法的時(shí)候,首先在當(dāng)前對(duì)象中查找
- 如果當(dāng)前對(duì)象中存儲(chǔ)著屬性或方法,停止查找,直接使用該屬性或方法
- 如果當(dāng)前對(duì)象沒(méi)有該成員,那么再在其原型對(duì)象中查找
- 如果原型對(duì)象中含有該成員,那么停止查找,直接使用
- 如果原型中還沒(méi)有,就到原型的原型中查找
- 如此往復(fù),直到Object.protitype還沒(méi)有,那么就返回undefined
- 如果是調(diào)用方法就報(bào)錯(cuò),該xxx不是一個(gè)函數(shù)
四、閉包
4.1 說(shuō)說(shuō)你對(duì)閉包的理解
實(shí)用閉包主要是為了設(shè)計(jì)私有方法和變量。閉包的優(yōu)點(diǎn)是可以避免全局變量的污染;缺點(diǎn)是閉包會(huì)常駐內(nèi)存,增加內(nèi)存使用量,使用不當(dāng)很容易造成內(nèi)存泄露。在JavaScript中,函數(shù)即閉包,只有函數(shù)才能產(chǎn)生作用域。
閉包有3個(gè)特性:
- 函數(shù)嵌套函數(shù)
- 在函數(shù)內(nèi)部可以引用外部的參數(shù)和變量
- 參數(shù)和變量不會(huì)以垃圾回收機(jī)制回收
4.2 閉包有什么用(特性)
閉包的作用,就是保存自己私有的變量,通過(guò)提供的接口(方法)給外部使用,但外部不能直接訪問(wèn)該變量。
通過(guò)使用閉包,我們可以做很多事情,比如模擬面向?qū)ο蟮拇a風(fēng)格;更優(yōu)雅,更簡(jiǎn)潔的表達(dá)出代碼;在某些方面提升代碼的執(zhí)行效率。利用閉包可以實(shí)現(xiàn)如下需求:
- 匿名自執(zhí)行函數(shù)
一個(gè)匿名的函數(shù),并立即執(zhí)行它,由于外部無(wú)法引用它內(nèi)部的變量,因此在執(zhí)行完后很快就會(huì)被釋放,關(guān)鍵是這種機(jī)制不會(huì)污染全局對(duì)象。
- 緩存
閉包正是可以做到這一點(diǎn),因?yàn)樗粫?huì)釋放外部的引用,從而函數(shù)內(nèi)部的值可以得以保留。
- 實(shí)現(xiàn)封裝
- 模擬面向?qū)ο蟮拇a風(fēng)格
4.3 閉包的基本模型
對(duì)象模式
函數(shù)內(nèi)部定義個(gè)一個(gè)對(duì)象,對(duì)象中綁定多個(gè)函數(shù)(方法),返回對(duì)象,利用對(duì)象的方法訪問(wèn)函數(shù)內(nèi)的數(shù)據(jù)
function createPerson() { var __name__ = ""; return { getName: function () { return __name__; }, setName: function( value ) { // 如果不姓張就報(bào)錯(cuò) if ( value.charAt(0) === '張' ) { __name__ = value; } else { throw new Error( '姓氏不對(duì),不能取名' ); } } } } var p = createPerson(); p.set_Name( '張三豐' ); console.log( p.get_Name() ); p.set_Name( '張王富貴' ); console.log( p.get_Name() );
函數(shù)模式
函數(shù)內(nèi)部定義一個(gè)新函數(shù),返回新函數(shù),用新函數(shù)獲得函數(shù)內(nèi)的數(shù)據(jù)
function foo() { var num = Math.random(); function func() { return mun; } return func; } var f = foo(); // f 可以直接訪問(wèn)這個(gè) num var res1 = f(); var res2 = f();
沙箱模式
沙箱模式就是一個(gè)自調(diào)用函數(shù),代碼寫(xiě)到函數(shù)中一樣會(huì)執(zhí)行,但是不會(huì)與外界有任何的影響,比如jQuery
(function () { var jQuery = function () { // 所有的算法 } // .... // .... jQuery.each = function () {} window.jQuery = window.$ = jQuery; })(); $.each( ... )
4.4 閉包的性能問(wèn)題
js 垃圾回收機(jī)制,也就是當(dāng)一個(gè)函數(shù)被執(zhí)行完后,其作用域會(huì)被收回,如果形成了閉包,執(zhí)行完后其作用域就不會(huì)被收回。
函數(shù)執(zhí)行需要內(nèi)存,那么函數(shù)中定義的變量,會(huì)在函數(shù)執(zhí)行結(jié)束后自動(dòng)回收,凡是因?yàn)殚]包結(jié)構(gòu)的,被引出的數(shù)據(jù),如果還有變量引用這些數(shù)據(jù)的話,那么這些數(shù)據(jù)就不會(huì)被回收。因此在使用閉包的時(shí)候如果不使用某些數(shù)據(jù)了,一定要賦值一個(gè)null
var f = (function () { var num = 123; return function () { return num; }; })(); // f 引用著函數(shù),函數(shù)引用著變量num // 因此在不使用該數(shù)據(jù)的時(shí)候,最好寫(xiě)上 f = null;
五、原型
5.1 什么是原型
一句話說(shuō)明什么是原型:原型能存儲(chǔ)我們的方法,構(gòu)造函數(shù)創(chuàng)建出來(lái)的實(shí)例對(duì)象能夠引用原型中的方法。
JS中一切皆對(duì)象,而每個(gè)對(duì)象都有一個(gè)原型(Object除外),這個(gè)原型,大概就像Java中的父類,所以,基本上你可以認(rèn)為原型就是這個(gè)對(duì)象的父對(duì)象,即每一個(gè)對(duì)象(Object除外)內(nèi)部都保存了它自己的父對(duì)象,這個(gè)父對(duì)象就是原型。一般創(chuàng)建的對(duì)象如果沒(méi)有特別指定原型,那么它的原型就是Object(這就很類似Java中所有的類默認(rèn)繼承自O(shè)bject類)。
ES6通過(guò)引入class
,extends
等關(guān)鍵字,以一種語(yǔ)法糖的形式把構(gòu)造函數(shù)包裝成類的概念,更便于大家理解。是希望開(kāi)發(fā)者不再花精力去關(guān)注原型以及原型鏈,也充分說(shuō)明原型的設(shè)計(jì)意圖和類是一樣的。
5.2 查看對(duì)象的原型
當(dāng)對(duì)象被創(chuàng)建之后,查看它們的原型的方法不止一種,以前一般使用對(duì)象的__proto__
屬性,ES6推出后,推薦用Object.getPrototypeOf()
方法來(lái)獲取對(duì)象的原型
function A(){ this.name='lala'; } var a=new A(); console.log(a.__proto__) //輸出:Object {} //推薦使用這種方式獲取對(duì)象的原型 console.log(Object.getPrototypeOf(a)) //輸出:Object {}
無(wú)論對(duì)象是如何創(chuàng)建的,默認(rèn)原型都是Object,在這里需要提及的比較特殊的一點(diǎn)就是,通過(guò)構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象,函數(shù)A本身也是一個(gè)對(duì)象,而A有兩個(gè)指向表示原型的屬性,分別是__proto__
和prototype
,而且兩個(gè)屬性并不相同
function A(){ this.name='lala'; } var a=new A(); console.log(A.prototype) //輸出:Object {} console.log(A.__proto__) //輸出:function () {} console.log(Object.getPrototypeOf(A)) //輸出:function () {}
函數(shù)的的prototype
屬性只有在當(dāng)作構(gòu)造函數(shù)創(chuàng)建的時(shí)候,把自身的prototype
屬性值賦給對(duì)象的原型。而實(shí)際上,作為函數(shù)本身,它的原型應(yīng)該是function
對(duì)象,然后function
對(duì)象的原型才是Object
。
總之,建議使用ES6推薦的查看原型和設(shè)置原型的方法。
5.3 原型的用法
其實(shí)原型和類的繼承的用法是一致的:當(dāng)你想用某個(gè)對(duì)象的屬性時(shí),將當(dāng)前對(duì)象的原型指向該對(duì)象,你就擁有了該對(duì)象的使用權(quán)了。
function A(){ this.name='world '; } function B(){ this.bb="hello" } var a=new A(); var b=new B(); //將b設(shè)置為a的原型,此處有一個(gè)問(wèn)題,即a的constructor也指向了B構(gòu)造函數(shù),可能需要糾正 Object.setPrototypeOf(a,b); a.constructor=A; console.log(a.bb); //hello
如果使用ES6來(lái)做的話則簡(jiǎn)單許多,甚至不涉及到prototype
這個(gè)屬性
class B{ constructor(){ this.bb='hello' } } class A extends B{ constructor(){ super(); this.name='world'; } } var a=new A(); console.log(a.bb+" "+a.name); //hello world console.log(typeof(A)) //"function"
怎么樣?是不是已經(jīng)完全看不到原型的影子了?活脫脫就是類繼承,但是你也看得到實(shí)際上類A 的類型是function
,所以說(shuō),本質(zhì)上class
在JS中是一種語(yǔ)法糖,JS繼承的本質(zhì)依然是原型,不過(guò),ES6引入class
,extends
來(lái)掩蓋原型的概念也是一個(gè)很友好的舉動(dòng),對(duì)于長(zhǎng)期學(xué)習(xí)那些類繼承為基礎(chǔ)的面對(duì)對(duì)象編程語(yǔ)言的程序員而言。
我的建議是,盡可能理解原型,盡可能用class
這種語(yǔ)法糖。
好了,問(wèn)自己兩個(gè)問(wèn)題:
- 為什么要使用原型?——提高函數(shù)的復(fù)用性。
-
為什么屬性不放在原型上而方法要放在原型上?
- 利用對(duì)象的動(dòng)態(tài)特性:
構(gòu)造函數(shù).prototype.xxxx = vvv
- 利用直接替換
Student.prototype = { sayHello : function(){}, study : function(){} };
- 利用對(duì)象的動(dòng)態(tài)特性:
5.4 原型鏈
什么是原型鏈?
凡是對(duì)象就有原型,那么原型又是對(duì)象,因此凡是給定一個(gè)對(duì)象,那么就可以找到他的原型,原型還有原型,那么如此下去,就構(gòu)成一個(gè)對(duì)象的序列,稱該結(jié)構(gòu)為原型鏈。
每個(gè)實(shí)例對(duì)象都有一個(gè)__proto_
屬性,該屬性指向它原型對(duì)象,這個(gè)實(shí)例對(duì)象 的構(gòu)造函數(shù)有一個(gè)原型屬性prototype
,與實(shí)例的__proto__
屬性指向同一個(gè)對(duì)象。當(dāng)一個(gè)對(duì)象在查找一個(gè)屬性的時(shí), 自身沒(méi)有就會(huì)根據(jù)__proto__
向它的原型進(jìn)行查找,如果都沒(méi)有,則向它的原型的原型繼續(xù)查找,直到查到Object.prototype._proto_
為null
,這樣也就形成了原型鏈
。
這個(gè)概念其實(shí)也變得比較簡(jiǎn)單,可以類比類的繼承鏈條,即每個(gè)對(duì)象的原型往上追溯,一直到Object為止,這組成了一個(gè)鏈條,將其中的對(duì)象串聯(lián)起來(lái),當(dāng)查找當(dāng)前對(duì)象的屬性時(shí),如果沒(méi)找到,就會(huì)沿著這個(gè)鏈條去查找,一直到Object,如果還沒(méi)發(fā)現(xiàn),就會(huì)報(bào)undefined
。
原型鏈的結(jié)構(gòu)
凡是使用構(gòu)造函數(shù),創(chuàng)建出對(duì)象,并且沒(méi)有利用賦值的方式修改原型,就說(shuō)該對(duì)象保留默認(rèn)的原型鏈。
默認(rèn)原型鏈結(jié)構(gòu)是什么樣子呢?
function Person(){} var p = new Person(); //p 具有默認(rèn)的原型鏈
默認(rèn)的原型鏈結(jié)構(gòu)就是:當(dāng)前對(duì)象 -> 構(gòu)造函數(shù).prototype -> Object.prototype -> null
在實(shí)現(xiàn)繼承的時(shí)候,有時(shí)候會(huì)利用替換原型鏈結(jié)構(gòu)的方式實(shí)現(xiàn)原型繼承,那么原型鏈結(jié)構(gòu)就會(huì)發(fā)生改變
function DunizbCollection(){} DunizbCollection.prototype = []; var arr = new DunizbCollection();
此時(shí)arr對(duì)象的原型鏈結(jié)構(gòu)被指向了數(shù)組對(duì)象的原型鏈結(jié)構(gòu)了:arr -> [] -> Array.prototype -> Object.prototype -> null
用圖形表示對(duì)象的原型鏈結(jié)構(gòu)
以如下代碼為例繪制原型鏈結(jié)構(gòu)
function Person(){} var p = new Person();
原型鏈結(jié)構(gòu)圖為:
使用原型需要注意兩點(diǎn):
- 原型繼承鏈條不要太長(zhǎng),否則會(huì)出現(xiàn)效率問(wèn)題。
- 指定原型時(shí),注意
constructor
也會(huì)改變。
六、繼承
實(shí)現(xiàn)繼承有兩種常見(jiàn)方式:
6.1 混合式繼承
最簡(jiǎn)單的繼承就是將別的對(duì)象的屬性強(qiáng)加到我身上,那么我就有這個(gè)成員了。
混合式繼承的簡(jiǎn)單描述:
function Person() {}; Person.prototype.extend = function ( o ) { for ( var k in o ) { this[ k ] = o[ k ]; } }; Person.prototype.extend({ run: function () { console.log( '我能跑了' ); }, eat: function () { console.log( '我可以吃了' ); }, sayHello: function () { console.log( '我吃飽了' ); } });
6.2 原型繼承
利用原型也可以實(shí)現(xiàn)繼承,不需要在我身上添加任何成員,只要原型有了我就有了。
6.3 借用構(gòu)造函數(shù)繼承
這種技術(shù)的基本思想相當(dāng)簡(jiǎn)單,即在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù),而函數(shù)只不過(guò)是在特定環(huán)境中執(zhí)行代碼的對(duì)象,因此通過(guò)使用apply()
和call()
方法也可以在(將來(lái))新創(chuàng)建的對(duì)象上執(zhí)行構(gòu)造函數(shù)
function Person ( name, age, gender ) { this.name = name; this.age = age; this.gender = gender; } // 需要提供一個(gè) Student 的構(gòu)造函數(shù)創(chuàng)建學(xué)生對(duì)象 // 學(xué)生也應(yīng)該有 name, age, gender, 同時(shí)還需要有 course 課程 function Student ( name, age, gender, course ) { Person.call( this, name, age, gender ); this.course = course; }
在《JavaScript高級(jí)程序設(shè)計(jì)(第三版)》中詳細(xì)介紹了繼承的6種方式
七、函數(shù)的四種調(diào)用模式
7.1 函數(shù)模式
就是一個(gè)簡(jiǎn)單的函數(shù)調(diào)用。函數(shù)名的前面沒(méi)有任何引導(dǎo)內(nèi)容。
function foo () {} var func = function () {}; ... foo(); func(); (function () {} )();
this 的含義:在函數(shù)中 this
表示全局對(duì)象,在瀏覽器中式 window
7.2 方法模式
方法一定式依附與一個(gè)對(duì)象,將函數(shù)賦值給對(duì)象的一個(gè)屬性,那么就成為了方法。
function f() { this.method = function () {}; } var o = { method: function () {} }
this
的含義:這個(gè)依附的對(duì)象
7.3 構(gòu)造器調(diào)用模式
創(chuàng)建對(duì)象的時(shí)候構(gòu)造函數(shù)做了什么?由于構(gòu)造函數(shù)只是給 this
添加成員,沒(méi)有做其他事情。而方法也可以完成這個(gè)操作,就是 this
而言,構(gòu)造函數(shù)與方法沒(méi)有本質(zhì)的區(qū)別。
特征:
- 使用
new
關(guān)鍵字,來(lái)引導(dǎo)構(gòu)造函數(shù)。 - 構(gòu)造函數(shù)中的
this
與方法中的一樣,表示對(duì)象,但是構(gòu)造函數(shù)中的對(duì)象是剛剛創(chuàng)建出來(lái)的對(duì)象 -
構(gòu)造函數(shù)中不需要
return
,就會(huì)默認(rèn)的return this
。- 如果手動(dòng)添加
return
,就相當(dāng)于return this
- 如果手動(dòng)的添加
return
基本類型,無(wú)效,還是保留原來(lái) 返回this
- 如果手動(dòng)添加的
return null
,或return undefined
,無(wú)效 - 如果手動(dòng)添加
return
對(duì)象類型,那么原來(lái)創(chuàng)建的this
就會(huì)被丟掉,返回的是return
后面的對(duì)象
- 如果手動(dòng)添加
7.4 上下文調(diào)用模式
上下文就是環(huán)境。就是自己定義設(shè)置 this 的含義。
語(yǔ)法
函數(shù)名.apply( 對(duì)象, [ 參數(shù) ] )
;函數(shù)名.call( 對(duì)象, 參數(shù) )
;
描述
- 函數(shù)名就是表示函數(shù)本身,使用函數(shù)進(jìn)行調(diào)用的時(shí)候默認(rèn) this 是全局變量
- 函數(shù)名也可以是方法提供,使用方法調(diào)用的時(shí)候,this 是指向當(dāng)前對(duì)象
- 使用 apply 進(jìn)行調(diào)用后,無(wú)論是函數(shù)還是方法都無(wú)效了,我們的 this ,由 apply 的第一個(gè)參數(shù)決定
參數(shù)問(wèn)題
無(wú)論是 call 還是 apply 在沒(méi)有后面的參數(shù)的情況下(函數(shù)無(wú)參數(shù),方法五參數(shù))是完全一致的
function foo(){ console.log( this ); } foo.apply( obj ); foo.call( obj );
第一個(gè)參數(shù)的使用也是有規(guī)則的:
- 如果傳入的是一個(gè)對(duì)象,那么就相當(dāng)于設(shè)置該函數(shù)中的 this 為參數(shù)
- 如果不傳入?yún)?shù),或傳入
null
、undefined
等,那么相當(dāng)于this
默認(rèn)為window
foo(); foo.apply(); foo.apply( null );
- 如果傳入的是基本類型,那么 this 就是基本類型對(duì)應(yīng)的包裝類型的引用
在使用上下文調(diào)用的時(shí)候,原函數(shù)(方法)可能會(huì)帶有參數(shù),那么這個(gè)參數(shù)再上下文調(diào)用中使用 第二個(gè)(第 n 個(gè))參數(shù)來(lái)表示
function foo( num ) { console.log( num ); } foo.apply( null, [ 123 ] ); // 等價(jià)于 foo( 123 );
參考資料
- 本文原型部分部分引用自《JavaScript原型詳解》,版權(quán)歸原作者所有
- js閉包的用途
感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun測(cè)試上述代碼運(yùn)行效果。
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《javascript面向?qū)ο笕腴T(mén)教程》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
微信小程序使用自定義組件導(dǎo)航實(shí)現(xiàn)當(dāng)前頁(yè)面高亮
這篇文章主要介紹了微信小程序使用自定義組件導(dǎo)航實(shí)現(xiàn)當(dāng)前頁(yè)面高亮,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01JavaScript常用的3種彈出框(提示框?alert/確認(rèn)框?confirm/輸入框?prompt)
三種彈框在系統(tǒng)中都是同步執(zhí)行的,也就是說(shuō),三種彈框中的任一彈框彈出,代碼都不在執(zhí)行,直到點(diǎn)擊確認(rèn)或取消,關(guān)閉彈窗后,代碼繼續(xù)執(zhí)行,本文通過(guò)實(shí)例代碼給大家分享JS常用的3種彈出框,感興趣的朋友一起看看吧2022-07-07js操作二級(jí)聯(lián)動(dòng)實(shí)現(xiàn)代碼
網(wǎng)上二級(jí)(多級(jí))聯(lián)動(dòng)的例子也不少,有各種不同的操作方法。我所采用的方法網(wǎng)上也應(yīng)該有的,不過(guò)我還沒(méi)有看到過(guò)。2010-07-07js 判斷計(jì)算字符串長(zhǎng)度/判斷空的簡(jiǎn)單方法
這篇文章介紹了判斷計(jì)算字符串長(zhǎng)度/判斷空的簡(jiǎn)單方法,有需要的朋友可以參考一下2013-08-08javaScript中Math()函數(shù)注意事項(xiàng)
本文主要給大家分享了javascript中Math()函數(shù)的注意事項(xiàng),以及math對(duì)象的方法,十分的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下2015-06-06js面向?qū)ο笾?、私有、靜態(tài)屬性和方法詳解
這篇文章主要詳細(xì)介紹了js面向?qū)ο笾小⑺接?、靜態(tài)屬性和方法,并附上詳細(xì)的示例,非常的細(xì)致全面,這里推薦給大家,有需要的小伙伴可以參考下2015-04-04原生javascript實(shí)現(xiàn)Tab選項(xiàng)卡切換功能
本文主要介紹了使用原生javascript實(shí)現(xiàn)Tab選項(xiàng)卡切換的功能,雖然jQuery有很多類似的插件,單jQuery庫(kù)著實(shí)有點(diǎn)龐大,這種小功能還是直接用javascript來(lái)做就好了。2015-01-01JS對(duì)象序列化成json數(shù)據(jù)和json數(shù)據(jù)轉(zhuǎn)化為JS對(duì)象的代碼
這篇文章主要介紹了JS對(duì)象序列化成json數(shù)據(jù)和json數(shù)據(jù)轉(zhuǎn)化為JS對(duì)象的代碼,需要的朋友可以參考下2017-08-08js中apply和Math.max()函數(shù)的問(wèn)題及區(qū)別介紹
這篇文章主要介紹了js中apply和Math.max()函數(shù)的問(wèn)題,本文給大家?guī)?lái)兩種答案,每一種答案給大家介紹的非常詳細(xì),在文章底部給大家提到了js中Math.max.apply和Math.max的區(qū)別,感興趣的朋友一起看看吧2018-03-03