摘要:目錄函數的聲明函數的屬性和方法函數的作用域閉包知識點小結關于函數,可以從以下個方面去理解首先,數據類型上看函數在中是一種數據類型,是對象的一種其次,從功能上看函數本質上是一段反復調用的代碼塊最后,從地位上看函數在中和其他基本數據類型一樣,可
目錄 1.函數的聲明 2.函數的屬性和方法 3.函數的作用域 4.閉包知識點 5.小結
關于函數,可以從以下3個方面去理解:
首先,數據類型上看:函數在JavaScript中是一種數據類型,是對象的一種;
其次,從功能上看:函數本質上是一段反復調用的代碼塊;
最后,從地位上看:函數在JavaScript中和其他基本數據類型一樣,可以作為參數和賦值,是“第一等公民”
聲明函數的方式有三種:
1.聲明式 function fn(){ console.log(1) } fn()//1
2.表達式 var fn = function(args){ console.log(args) } fn(a)//a
3.構造函數式 var fn = new Function("arg1","arg2","return arg1+arg2") fn(1,2)//3
函數本質上是對象的一種,所以函數名保存的實際上是指向函數對象的指針,第3種構造函數的方法對于理解“函數是對象,函數名是指針”的概念更加直觀,但是第3種方法解析效率較低而且書寫不簡潔,所以一般不用構造函數方法去聲明函數;
當聲明式和表達式同時聲明同一個函數時,表達式會覆蓋聲明式,原因是函數作為變量在js解析階段進行變量提升,聲明式和表達式都會提升至當前作用域頭部,然后表達式會重新為fn賦值,從而覆蓋聲明式定義的函數;
function fn(){ console.log(1) } var fn = function(){ console.log(2) } fn()//2
關于return語句的理解,如果聲明的函數沒有return語句,則默認return undefined,否則返回定義的值;
var a = function(){ console.log(1) } var b = function(){ return 2; } a() === undefined//true2.函數的屬性和方法
函數作為一個對象,同樣擁有屬性和方法,下面主要歸納一下比較常用和重要的屬性和方法:
name屬性:返回該函數名的字符串;
length屬性:返回形參的個數,即預期傳入參數的個數;
function fn (a,b){ console.log(fn.name) console.log(fn.length) } fn() //"fn" //2
arguments對象:是包含傳入函數實參的類數組對象,只有在函數執行階段并且存在參數才會有值,未調用函數是為null;
function fn (a,b){ console.log(arguments) } fn(1,2) //[1,2]
arguments對象的length屬性代表實參的個數,注意和函數的length屬性的區別,函數的length代表形參的個數,arguments的length屬性代表實參個數;
arguments對象有一個callee屬性,返回arguments對象所在的函數指針;
可以利用callee實現函數的遞歸,例如累加或階乘操作:
function increment(arg){ if(arg === 1){ return 1 } return arg+arguments.callee(arg-1) } function increMultipler(arg){ if(arg === 1){ return 1 } return arg*arguments.callee(arg-1) }
這里另外提一個函數的caller屬性,該屬性保存調用當前函數的函數的引用,注意的是如果在全局作用域下讀取該屬性,值為null,因為頂層對象在瀏覽器中為window不是函數;
function outer(){ inner(); } function inner(){ console.log(arguments.callee.caller) } outer();
this對象:代表函數執行時的環境對象,簡單的說就是誰調用了該函數,this的指向是動態的,只有在函數調用時this對象才能確定;
//在瀏覽器全局環境下,即window對象下 var print = function(){ console.log(this) } print()//this指向Window,因為這是Window對象調用了print方法 //在特定對象的環境下 var o = { print: function(){ console.log(this) } } o.print()//this指向o,因為這是o對象調用print方法
函數提供call、apply和bind3種方法可以改變this對象;
1.call方法 function fn(){ return this } var o = {} fn() === this//true,this指向window對象 fn.call(o) === o//true,this指向o對象 //call方法還可以傳入參數; function add(x,y){ return x+y } add.call(null,1,2)
2.apply方法,與call不同的是apply傳入的參數為數組 var arr = [1,2] function add(x,y){ return x+y } add.apply(null,arr)
實際上,apply和call的區別只在于傳遞參數的不同,它們真正強大的地方在于能夠擴充函數賴以運行的作用域,比如slice函數原本只存在于數組當中,當中通過使用call方法,可以實現不同作用域下調用該方法;
function fn(a,b){ console.log(Array.prototype.slice.call(arguments)) } fn(1,2)//[1,2]
bind方法會創建一個函數實例,并將該函數的this對象綁定到傳入該方法的參數;
function fn(){ return this } var o = {} var newFn =fn.bind(o) newFn() === o//true更多this的相關介紹,詳見【what"s this???】 3.函數的作用域
作用域指的是變量存在的范圍,作用域可分為全局作用域和局部作用域,變量在全局范圍可訪問到;局部作用域由函數所構造,變量只能在函數內部可訪問到;
var a =1//a處于全局作用域 function fn(){ var a = 2//a處于局部作用域,外部無法訪問; return a; } a//1 fn()//2
值的注意的是,函數執行時所在的作用域是定義時所在的作用域,而不是調用時所在的作用域;
var a = 1; function fn(){ console.log(a) } function fn2(){ var a = 2; fn() } fn2()//14. 閉包知識點
關于閉包的知識點,將會多帶帶開一章節詳談,具體請看《JavaScript閉包(三)》
5.小結通過《JavaScript函數(二)》,我們大致了解關于函數的知識點如下:
函數本質上是一段反復調用的代碼塊,是對象的一種,在js中作為“第一等公民”,可以賦值和傳參;
函數聲明的方法有3種:聲明式、表達式和構造函數式;其中構造函數是能夠直觀理解函數的“函數是對象,函數名是指針”的概念;當表達式和聲明式同時聲明同名函數時,表達式會覆蓋聲明式,原因是變量提升的作用;
函數作為對象,同樣具有屬性和方法;name返回該函數名的字符串,length返回形參的個數;
arguments對象是包含傳入函數的實參的類數組對象,只有在執行階段該對象才有值,未調用函數時為null,arguments.length表示實參的個數,arguments.callee返回arguments對象所在的函數的指針;
函數的caller返回調用當前函數的函數的指針,在全局作用域下讀取該屬性為null;
this對象代表當前函數執行時的環境對象,this對象只有在函數執行階段才能確定;
可以使用call、apply和bind改變this的指向;call和apply的區別在于二者傳遞的參數不同,call為零散的數據,apply為數組,二者最大的用處是擴展函數的作用域;bind方法可以返回一個函數的實例,并綁定this對象至傳入bind的參數;
函數可以開辟一個獨立的作用域,這使得js當中經典的閉包得以實現提供可能性;此外,函數執行時所在的作用域是在定義時所在的作用域,而不是調用時所在的作用域;
參考資料《JavaScript高級程序設計(第3版)》
《JavaScript標準參考教程》——阮一峰
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/86582.html
摘要:使用實現排序二叉樹排序二叉樹的定義二叉樹的基礎上,左節點比父節點要小,右節點比父節點要大的二叉樹,叫排序二叉樹。下期內容實現排序二叉樹的中序前序后續遍歷實現二叉樹的節點查找功能實現排序二叉樹的刪除節點功能應用排序二叉樹實現一個小游戲 使用javascript實現排序二叉樹(1) 排序二叉樹的定義: 二叉樹的基礎上,左節點比父節點要小,右節點比父節點要大的二叉樹,叫排序二叉樹。 show...
摘要:講作用域鏈首先要從作用域講起,下面是百度百科里對作用域的定義作用域在許多程序設計語言中非常重要。原文出處談談語法里一些難點問題二 3) 作用域鏈相關的問題 作用域鏈是javascript語言里非常紅的概念,很多學習和使用javascript語言的程序員都知道作用域鏈是理解javascript里很重要的一些概念的關鍵,這些概念包括this指針,閉包等等,它非常紅的另一個重要原因就...
摘要:策略模式實現的也是類似的場景。第二個部分是環境類不變,接收客戶的請求,隨后把請求委托給某一個策略類。參考文章設計模式設計模式與開發實踐設計模式系統講解與應用本文首發,期待作者以樂之名本文原創,有不當的地方歡迎指出。 showImg(https://segmentfault.com/img/bVbugi7?w=800&h=600); 策略模式:定義一系列的算法,把它們一個個封裝起來,并且...
摘要:一作用域域表示的就是范圍,即作用域,就是一個名字在什么地方可以使用,什么時候不能使用。概括的說作用域就是一套設計良好的規則來存儲變量,并且之后可以方便地找到這些變量。 一、作用域 域表示的就是范圍,即作用域,就是一個名字在什么地方可以使用,什么時候不能使用。想了解更多關于作用域的問題推薦閱讀《你不知道的JavaScript上卷》第一章(或第一部分),從編譯原理的角度說明什么是作用域。概...
摘要:前言書接上文細數實用黑科技一本文介紹獨孤九劍和兩篇最高內功心法??梢詫⒆兞哭D換為布爾值??梢园讶魏晤愋偷闹缔D換為布爾值,并且只有當這個變量的值為的時候才會返回,其他情況都返回。同樣的,函數體內部聲明的函數,作用域綁定函數體內部。 showImg(https://segmentfault.com/img/remote/1460000016507838); 前言 書接上文:細數 JavaS...
摘要:屬性是一個值或一組值以數組或對象的形式,是對象的成員??梢允褂脙戎脴嬙旌瘮岛蛣摻òb對象。因此下面的代碼將會使人很迷惑結果結果,此數組長度為應該盡量避免使用數組構造函數創建新數組。給數組對象添加返回數組中最大元素值的方法。 對象部分 Object類型 Object 是一個無序的集合,可以存放任意類型對象,所有其他對象都繼承自這個對象。創建Object類型有兩種,一種是使用new運算符,...
閱讀 2715·2023-04-26 02:02
閱讀 2576·2023-04-25 20:38
閱讀 4111·2021-09-26 09:47
閱讀 3099·2021-09-10 10:50
閱讀 3767·2021-09-07 09:58
閱讀 3332·2019-08-30 15:54
閱讀 2698·2019-08-30 15:54
閱讀 1921·2019-08-29 17:03