摘要:函數(shù)聲明根據(jù)規(guī)則,進(jìn)入執(zhí)行上下文會自動聲明形參并且賦值,但是同名的函數(shù)聲明會替換這個變量。的函數(shù)調(diào)用得到其返回值。的意義在于將執(zhí)行的結(jié)果通知給代理函數(shù)進(jìn)行及時處理。回調(diào)函數(shù)的傳遞傳遞的方式有兩種,函數(shù)引用和函數(shù)表達(dá)式。
函數(shù)聲明方式 匿名函數(shù)
function后面直接跟括號,中間沒有函數(shù)名的就是匿名函數(shù)。
let fn = function() { console.log("我是fn") } let fn2 = fn console.log(fn.name) //fn console.log(fn2.name)//fn,fn和fn2指向的是同一個function。具名函數(shù)
function后面有函數(shù)名字的,不是直接跟括號的的就是具名函數(shù)。
如果把一個具名函數(shù)賦值給一個變量,那么這個具名函數(shù)的作用域就不是window了。
let fn = function fn1() { console.log("function") } console.log(fn.name) //fn1 console.log(fn1,name) // ReferenceError: fn1 is not defined箭頭函數(shù)
箭頭函數(shù)是es6知識點,具有以下幾個特點:
如果只有一個參數(shù),可以省略小括號。
如果有至少有兩個參數(shù),必須加小括號。
如果函數(shù)體只有一句話可以省略花括號,并且這一句作為返回值return。
如果函數(shù)體至少有兩句必須加上花括號。
箭頭函數(shù)里面是沒有this的。
let fn = e => e+1 console.log(fn(1)) //2 let fn1 = (i,y) => i+y console.log(fn1(2,3)) //5 let fn2 = (i,y) => { i+=1; y+=2; return i+y } console.log(fn2(5,6)) //13詞法作用域(靜態(tài)作用域)
靜態(tài)作用域又叫做詞法作用域,采用詞法作用域的變量叫詞法變量。詞法變量有一個在編譯時靜態(tài)確定的作用域。詞法變量的作用域可以是一個函數(shù)或一段代碼,該變量在這段代碼區(qū)域內(nèi)可見(visibility);在這段區(qū)域以外該變量不可見(或無法訪問)。詞法作用域里,取變量的值時,會檢查函數(shù)定義時的文本環(huán)境,捕捉函數(shù)定義時對該變量的綁定。
詞法作用域:變量的作用域是在定義時決定而不是執(zhí)行時決定,也就是說詞法作用域取決于源碼,通過靜態(tài)分析就能確定,因此詞法作用域也叫做靜態(tài)作用域。 with和eval除外,所以只能說JS的作用域機(jī)制非常接近詞法作用域(Lexical scope)。
通過詞法作用域樹能判斷變量指向關(guān)系,但是不能斷定變量的值,變量的值還需要根據(jù)執(zhí)行順序進(jìn)一步作出判斷,看一下例子:
因為JavaScript采用的是詞法作用域,bian"liang的作用域基于函數(shù)創(chuàng)建的位置,跟調(diào)用時的位置無關(guān)。
var i = 1, j = 2, k = 3; function a(o, p, x, q) { var x = 4; alert(i); function b(r, s) { var i = 11, y = 5; alert(i); function c(t) { var z = 6; alert(i); }; var d = function() { alert(y); }; c(60); d(); }; b(40, 50); } a(10, 20, 30); //1 11 11 5
/** * 模擬建立一棵語法分析樹,存儲function內(nèi)的變量和方法 */ var SyntaxTree = { // 全局對象在語法分析樹中的表示 window: { variables:{ i:{ value:1}, j:{ value:2}, k:{ value:3} }, functions:{ a: this.a } }, a:{ variables:{ x:"undefined" }, functions:{ b: this.b }, scope: this.window }, b:{ variables:{ i:"undefined" y:"undefined" }, functions:{ c: this.c, d: this.d }, scope: this.a }, c:{ variables:{ z:"undefined" }, functions:{}, scope: this.b }, d:{ variables:{}, functions:{}, scope: { scope: this.b } } };
/** * 活動對象:函數(shù)執(zhí)行時創(chuàng)建的活動對象列表 */ let ActiveObject = { window: { variables: { i: { value: 1 } j: { value: 2 } k: { value: 3 } }, functions: { a: this.a } } a: { variables: { x: { vale: 4 }, functions: { b: this.b }, scope: this.window, params: { o: { value: 10 }, p: { value: 20 }, x: this.variables.x q: { vale: "undefined" } }, arguments: [this.params.o, this.params.p, this.params.x] } } b: { variables: { i: { vale: 11 }, y: { vale: 5 }, }, functions: { c: this.c, d: this.d }, params: { r: { value: 40 } s: { value: 50 } }, arguments: [this.params.r, this.params.scope] scope: this.a } c: { variables: { z: { value: 6 }, functions: {}, params: { t: { value: 60 } }, arguments: [this.params.t] scope: this.b } } d: { variables: {}, functions: {}, params: {}, arguments: [] this.scope: this.b } }call stack
進(jìn)入call stack 時的一些規(guī)則:
函數(shù)的所有形參(如果我們是在函數(shù)執(zhí)行上下文中)
由名稱和對應(yīng)值組成的一個變量對象的屬性被創(chuàng)建;沒有傳遞對應(yīng)參數(shù)的話,那么由名稱和 undefined 值組成的一種變量對象的屬性也將被創(chuàng)建。
所有函數(shù)聲明(FunctionDeclaration, FD)
由名稱和對應(yīng)值(函數(shù)對象(function-object))組成一個變量對象的屬性被創(chuàng)建;如果變量對象已經(jīng)存在相同名稱的屬性,則完全替換這個屬性。
所有變量聲明(var, VariableDeclaration)
由名稱和對應(yīng)值(undefined)組成一個變量對象的屬性被創(chuàng)建;如果變量名稱跟已經(jīng)聲明的形式參數(shù)或函數(shù)相同,則變量聲明不會干擾已經(jīng)存在的這類屬性。
/* * example1:形參 */ function test(a, b) { /* var a = 10 var b = undefined 根據(jù)規(guī)則1,在進(jìn)入執(zhí)行上下文時會自動對形參聲明并且賦值。 */ console.log(a) var c = 10; function d() {} var e = function _e() {}; (function x() {}); } test(10); // 10
/* * example2:函數(shù)聲明 */ function test(a, b) { console.log(a) function a() {} var e = function _e() {}; } test(10); // ? a() {} .根據(jù)規(guī)則2,進(jìn)入執(zhí)行上下文會自動聲明形參并且賦值,但是同名的函數(shù)聲明會替換這個變量。 function test(a, b) { console.log(a) var a = 30; var a = function _e() {}; } test(10); // 10 .根據(jù)規(guī)則2,進(jìn)入執(zhí)行上下文會自動聲明形參并且賦值,但是同名的函數(shù)聲明會替換這個變量。
/* * example3:變量聲明 */ console.log(foo);//會打印出foo函數(shù),根據(jù)規(guī)則3,同名的變量聲明不會干擾函數(shù)聲明和形參 function foo(){ console.log("foo"); } var foo = 1;this和arguments 函數(shù)調(diào)用
在es5中,函數(shù)有四種調(diào)用方式:
1. fn(p1,p2) 2. obj.fn(p1,p2) 3. fn.call(context,p1,p2) 4. fn.apply(context,p1,p2)
第三和第四種才是正常的js函數(shù)調(diào)用方式,其他兩種就是語法糖。
fn(p1,p2) 等價于 fn.call(undefined,p1,p2) 等價于 fn.apply(context,[p1,p2]) obj.fn(p1,p2) 等價于 obj.fn.call(obj,p1,p2) 等價于 obj.fn.apply(obj,[p1,p2])
如果你傳的 context 就 null 或者 undefined,那么 window 對象就是默認(rèn)的 context(嚴(yán)格模式下默認(rèn) context 是 undefined)this是什么??
this是call的第一個參數(shù)?。。。?/strong>
var obj = { foo: function(){ console.log(this) } } var bar = obj.foo obj.foo() // 打印出的 this 是 obj bar() // 打印出的 this 是 window
obj.foo() 相當(dāng)于 obj.foo.call(obj) 也就相當(dāng)于把函數(shù)名前面的作為call的第一個參數(shù),也就是this,如果沒有就是window。 bar() 相當(dāng)于 bar.call(undefined)
在執(zhí)行函數(shù)的時候,this是隱藏的一個參數(shù),且必須是一個對象,如果不是,js是自動把它轉(zhuǎn)為對象。
function fn() { console.log(this) console.log(arguments) } fn.call(1,2,3) // Number?{1} [2,3]arguments
arguments是偽數(shù)組它類似于Array,但除了length屬性和索引元素之外沒有任何Array屬性。
call和apply里面除了第一個參數(shù)之外的都是arguments,如果arguments的個數(shù)少建議使用call,使用apply也可以,如果不確定就使用apply。
使用一下方法吧arguments轉(zhuǎn)為真正的數(shù)組:
var args = Array.prototype.slice.call(arguments); var args = [].slice.call(arguments); // ES2015 const args = Array.from(arguments); const args = [...arguments]bind
MDN 官方文檔對 bind() 的定義:
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
大概意思就是,bind會返回一個新的函數(shù)(并沒有的調(diào)用原來的函數(shù)),這個新函數(shù)會call原來的函數(shù),call的參數(shù)由你決定??蠢樱?/p>
this.x = 9; var module = { x: 81, getX: function() { return this.x; } }; var retrieveX = module.getX; var boundGetX = retrieveX.bind(module); boundGetX(); // 81
retrieveX.bind(module)返回了一個新的函數(shù)boundGetX,然后調(diào)用這個新的函數(shù)的時候,把這個函數(shù)里面的this綁定到了module對象上,所以this.x就相當(dāng)于module.x也就是等于81.
柯里化在計算機(jī)科學(xué)中,柯里化(英語:Currying),又譯為卡瑞化或加里化,是把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。這個技術(shù)由克里斯托弗·斯特雷奇以邏輯學(xué)家哈斯凱爾·加里命名的,盡管它是Moses Sch?nfinkel和戈特洛布·弗雷格發(fā)明的。
說的明白一點就是,給函數(shù)傳遞一部分參數(shù),讓它返回一個函數(shù)去處理其他參數(shù),舉個例子,求三個數(shù)之和:
let addOne = function add(x) { return function(y) { return function(z) { return x+y+z } } } let one = addOne(3) console.log(one)//? (y) {return function (z) {return x + y + z}} let two = one(4) console.log(two)//? (z) {return x + y + z} let three = two(5) console.log(three)//12
javascript函數(shù)柯里化--詳細(xì)說明鏈接
高階函數(shù)在數(shù)學(xué)和計算機(jī)科學(xué)中,高階函數(shù)是至少滿足下列一個條件的函數(shù):
接受一個或多個函數(shù)作為輸入
輸出一個函數(shù)
舉一些高階函數(shù)的例子:
/* *接受一個或多個函數(shù)作為輸入 */ 1. Array.prototype.filter() 2. Array.prototype.forEach() 3. Array.prototype.reduce() 4. Array.prototype.map() 5. Array.prototype.find() 6. Array.prototype.every()
/* *輸出一個函數(shù) */ 1. fn.bind(args)回調(diào)函數(shù)
函數(shù)A作為參數(shù)(函數(shù)引用)傳遞到另一個函數(shù)B中,并且這個函數(shù)B執(zhí)行函數(shù)A。我們就說函數(shù)A叫做回調(diào)函數(shù)。如果沒有名稱(函數(shù)表達(dá)式),就叫做匿名回調(diào)函數(shù)。
名詞形式:被當(dāng)做參數(shù)的函數(shù)就是回調(diào)
動詞形式:調(diào)用這個回調(diào)
注意回調(diào)跟異步?jīng)]有任何關(guān)系
資源加載:動態(tài)加載js文件后執(zhí)行回調(diào),加載iframe后執(zhí)行回調(diào),ajax操作回調(diào),圖片加載完成執(zhí)行回調(diào),AJAX等等。
DOM事件及Node.js事件基于回調(diào)機(jī)制(Node.js回調(diào)可能會出現(xiàn)多層回調(diào)嵌套的問題)。
setTimeout的延遲時間為0,這個hack經(jīng)常被用到,settimeout調(diào)用的函數(shù)其實就是一個callback的體現(xiàn)
鏈?zhǔn)秸{(diào)用:鏈?zhǔn)秸{(diào)用的時候,在賦值器(setter)方法中(或者本身沒有返回值的方法中)很容易實現(xiàn)鏈?zhǔn)秸{(diào)用,而取值器(getter)相對來說不好實現(xiàn)鏈?zhǔn)秸{(diào)用,因為你需要取值器返回你需要的數(shù)據(jù)而不是this指針,如果要實現(xiàn)鏈?zhǔn)椒椒?,可以用回調(diào)函數(shù)來實現(xiàn)。
setTimeout、setInterval的函數(shù)調(diào)用得到其返回值。由于兩個函數(shù)都是異步的,即:他們的調(diào)用時序和程序的主流程是相對獨立的,所以沒有辦法在主體里面等待它們的返回值,它們被打開的時候程序也不會停下來等待,否則也就失去了setTimeout及setInterval的意義了,所以用return已經(jīng)沒有意義,只能使用callback。callback的意義在于將timer執(zhí)行的結(jié)果通知給代理函數(shù)進(jìn)行及時處理。
回調(diào)函數(shù)的傳遞傳遞的方式有兩種,函數(shù)引用和函數(shù)表達(dá)式。
$.get("myhtmlpage.html", myCallBack);//這是對的 $.get("myhtmlpage.html", myCallBack("foo", "bar"));//這是錯的,那么要帶參數(shù)呢? $.get("myhtmlpage.html", function(){//帶參數(shù)的使用函數(shù)表達(dá)式 myCallBack("foo", "bar"); });箭頭函數(shù)與es5的函數(shù)主要區(qū)別
箭頭函數(shù)的主要區(qū)別在this,箭頭函數(shù)是沒有this這個概念的,看例子:
setTimeout(function(a){ console.log(this) //這個this指的是{name:"Jack"} setTimeout(function(a){ console.log(this) //這個this指的是window,因為沒有bind,調(diào)用setTimeout的是window },1000) }.bind({name:"Jack"}),1000)
setTimeout(function(a){ console.log(this) //這個this指的是{name:"Jack"} setTimeout(function(a){ console.log(this) //這個this指的是{name: "Jack"},因為bind了外面的this也就是{name: "Jack"} },1000) }.bind({name:"Jack"}),1000)
setTimeout(function(a){ console.log(this) //這個this指的是{name:"Jack"} setTimeout(a=>console.log(this),1000)//這個this指的是{name:"Jack"},因為箭頭函數(shù)沒有this的概念,它指的this就是外面的this,也就是{name:"Jack"} }.bind({name:"Jack"}),1000)
至此基本上說了js的所有函數(shù)內(nèi)容,只是簡單舉個例子,更深入的研究還需要看一些其他大佬的博客哦~~~~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93395.html
摘要:基本類型有六種,,,,,。類型是類數(shù)組,具有基礎(chǔ)類型檢測檢測基礎(chǔ)類型用只適合檢測基礎(chǔ)類型基礎(chǔ)類型轉(zhuǎn)換基本類型轉(zhuǎn)換時,首先會調(diào)用,然后調(diào)用。該方法在轉(zhuǎn)基本類型時調(diào)用優(yōu)先級最高。 夯實Javascript基礎(chǔ)。 基本類型有六種: null,undefined,boolean,number,string,symbol。 基本類型的值是保存在棧內(nèi)存中的簡單數(shù)據(jù)段 基礎(chǔ)類型特性 基礎(chǔ)類型最重要的...
摘要:基本類型有六種,,,,,。類型是類數(shù)組,具有基礎(chǔ)類型檢測檢測基礎(chǔ)類型用只適合檢測基礎(chǔ)類型基礎(chǔ)類型轉(zhuǎn)換基本類型轉(zhuǎn)換時,首先會調(diào)用,然后調(diào)用。該方法在轉(zhuǎn)基本類型時調(diào)用優(yōu)先級最高。 夯實Javascript基礎(chǔ)。 基本類型有六種: null,undefined,boolean,number,string,symbol。 基本類型的值是保存在棧內(nèi)存中的簡單數(shù)據(jù)段 基礎(chǔ)類型特性 基礎(chǔ)類型最重要的...
摘要:基本類型有六種,,,,,。類型是類數(shù)組,具有基礎(chǔ)類型檢測檢測基礎(chǔ)類型用只適合檢測基礎(chǔ)類型基礎(chǔ)類型轉(zhuǎn)換基本類型轉(zhuǎn)換時,首先會調(diào)用,然后調(diào)用。該方法在轉(zhuǎn)基本類型時調(diào)用優(yōu)先級最高。 夯實Javascript基礎(chǔ)。 基本類型有六種: null,undefined,boolean,number,string,symbol。 基本類型的值是保存在棧內(nèi)存中的簡單數(shù)據(jù)段 基礎(chǔ)類型特性 基礎(chǔ)類型最重要的...
摘要:曾幾何時,閉包好像就是一個十分難以捉摸透的東西,看了很多文章,對閉包都各有說法,以致讓我十分暈,什么內(nèi)部變量外部變量的,而且大多數(shù)都只描述一個過程,沒有給閉包的定義,最后,舉幾個例子,告訴你這就是閉包。 曾幾何時,閉包好像就是一個十分難以捉摸透的東西,看了很多文章,對閉包都各有說法,以致讓我十分暈,什么內(nèi)部變量、外部變量的,而且大多數(shù)都只描述一個過程,沒有給閉包的定義,最后,舉幾個例子...
摘要:最近在代碼中不小心不規(guī)范的,在里面定義了塊級變量,導(dǎo)致頁面在某些瀏覽器中出錯,本文討論以下語句中的塊級作用域。而與無關(guān)每一個并不會構(gòu)成一個獨立的塊級作用域。 ??最近在代碼中不小心不規(guī)范的,在switch里面定義了塊級變量,導(dǎo)致頁面在某些瀏覽器中出錯,本文討論以下switch語句中的塊級作用域。 switch語句中的塊級作用域 switch語句中的塊級作用域可能存在的問題 規(guī)范和檢...
閱讀 1902·2021-11-22 15:25
閱讀 1260·2021-11-19 09:40
閱讀 1870·2021-09-27 13:57
閱讀 1002·2021-09-22 15:10
閱讀 980·2021-08-16 11:01
閱讀 2980·2021-07-23 17:51
閱讀 777·2019-08-30 15:55
閱讀 827·2019-08-30 13:58