關(guān)于函數(shù)

看到代碼就開始答題,必錯(cuò)!!!聲明提前?。。∽兞刻嵘。。?/p>

一、函數(shù)的 5 種聲明(重點(diǎn)匿名,具名,箭頭)

  • 1、具名函數(shù)
function f(x,y){
     return x+y
 }
 f.name // 'f'
var f5 = function f4(){ //f4的作用域是這個(gè)函數(shù)本身
 
}
console.log(f);//可訪問
  • 2、匿名函數(shù)
var f
 f = function(x,y){ //f引用函數(shù) f記錄的是函數(shù)的地址,不是函數(shù)本身
     return x+y
 }
var f2 = f;//復(fù)制的函數(shù)地址,同時(shí)指向函數(shù)
 f.name // 'f' ,他是匿名函數(shù),但是他有name
 f2.name // 'f'
  • 3、具名函數(shù)賦值
var f
 f = function f2(x,y){ return x+y }
 f.name // 'f2'
 console.log(f2) // undefined
  • 4、window.Function
 var f = new Function('x','y','return x+y')
 f.name // "anonymous"
  • 5、箭頭函數(shù)
    var fn6 = i=>i+1 //一個(gè)參數(shù)
    var fn7 = (i,j)=>i+j //兩個(gè)參數(shù)
    var fn8 = (i,j)=>{console.log(1);return i+j;}//執(zhí)行多條內(nèi)容,用{括起來}
 var f = (x,y) => {
     return x+y
 }
 var sum = (x,y) => x+y
 var n2 = n => n*n

這幾種方法大體相同,只是this不同

二、如何調(diào)用函數(shù)

f.call(asThis, input1,input2)
其中 asThis 會(huì)被當(dāng)做 this,[input1,input2] 會(huì)被當(dāng)做 arguments
禁止使用 f(input1, input2)

三、作用域

  • 按照語法樹,就近原則
  • 我們只能確定變量是哪個(gè)變量,但是不能確定變量的值
    拿到代碼直接做——必然會(huì)錯(cuò)。請(qǐng)先提升聲明!!!(只提聲明,不帶值)
    詞法作用域(靜態(tài)作用域)練習(xí):
var global1 = 1
 function fn1(param1){
     var local1 = 'local1'
     var local2 = 'local2')
     function fn2(param2){
         var local2 = 'inner local2'
         console.log(local1)
         console.log(local2)
     }

     function fn3(){
         var local2 = 'fn3 local2'
         fn2(local2)
     }
 }
詞法樹.png

詞法樹只用來分析語義,和值沒有關(guān)系
面試題1

var aa = 1;
function f(){
  console.log(aa)
}
aa = 2;
f.call()
var a = 1
function f1(){
    alert(a) // 是多少
    var a = 2
}
f1.call()

答案:

var a = 1
function f1(){
     var a //聲明提前
    alert(a) // undefined
     a = 2
}
f1.call()

面試題2

var a = 1
function f1(){
    var a = 2
    f2.call()
}
function f2(){
    console.log(a) // 是多少
}
f1.call()

答案:

var a = 1
function f1(){
    var a = 2 //a=2只在當(dāng)前作用域(f1)內(nèi)有效
    f2.call() 
}
function f2(){
    console.log(a) //1,拿的是全局a = 1
}
f1.call()

面試題3

var liTags = document.querySelectorAll('li')
for(var i = 0; i<liTags.length; i++){
    liTags[i].onclick = function(){
        console.log(i) // 點(diǎn)擊第3個(gè) li 時(shí),打印 2 還是打印 6?
    }
}

深入閱讀:

四、什么是 call stack

stack堆:先進(jìn)后出
隊(duì)列:先進(jìn)先出
瀏覽器不是先運(yùn)行代碼,而是先把申明提到前面


圖片.png

五、this 和 arguments

function f(){
      console.log(this)
      console.log(arguments)
  }
  f.call() // window
  f.call({name:'frank'}) // {name: 'frank'}, []
  f.call({name:'frank'},1) // {name: 'frank'}, [1]
  f.call({name:'frank'},1,2) // {name: 'frank'}, [1,2]

不傳this,默認(rèn)window
不傳arguments,默認(rèn)是空數(shù)組[]
為什么用call,不用f()直接調(diào),用f()是閹割版的f.call(),就不容易分辨出this代表是什么

function f(){
    'use strict'
    console.log(this)
    console.log(arguments)
    return undefined
}
f.call();//需傳入this和arguments([]),如果沒有傳,window不給this,就默認(rèn)是undefined,也就是window(小寫window,google瀏覽器打印出來是Window,所以運(yùn)行結(jié)果是window,[]
f.call(1,2,3) // this 為 1,arguments 為 [2,3]
  • this為什么必須是對(duì)象

因?yàn)?this 就是函數(shù)與對(duì)象之間的羈絆

var person = {
          name: 'frank',
          sayHi: function(person){
              console.log('Hi, I am' + person.name)
          },
          sayBye: function(person){
              console.log('Bye, I am' + person.name)
          },
          say: function(person, word){
              console.log(word + ', I am' + person.name)
          }
      }
      person.sayHi(person)
      person.sayBye(person)
      person.say(person, 'How are you')

      // 能不能變成 
      person.sayHi()
      person.sayBye()
      person.say('How are you')

      // 那么源代碼就要改了
      var person = {
          name: 'frank',
          sayHi: function(){
              console.log('Hi, I am' + this.name)
          },
          sayBye: function(){
              console.log('Bye, I am' + this.name)
          },
          say: function(word){
              console.log(word + ', I am' + this.name)
          }
      }
      // 如果你不想吃語法糖
      person.sayHi.call(person)
      person.sayBye.call(person)
      person.say.call(person, 'How are you')

      // 還是回到那句話:this 是 call 的第一個(gè)參數(shù)
      // this 是參數(shù),所以,只有在調(diào)用的時(shí)候才能確定
      person.sayHi.call({name:'haha'})  // 這時(shí) sayHi 里面的 this 就不是 person 了
      // this 真的很不靠譜

      // 新手疑惑的兩種寫法
      var fn = person.sayHi
      person.sayHi() // this === person
      fn()  // this === window
sum(x,y){
  return x+y
}
sum.call(undefined,1,2);//undefined必須寫

六、call / apply

n.call(asThis, p1,p2) 是函數(shù)的正常調(diào)用方式
當(dāng)你不確定參數(shù)的個(gè)數(shù)時(shí),就使用 apply
fn.apply(asThis, params)

function sum(){
  var n = 0;
  for(var i = 0;i<arguments.length;i++){
    n+= arguments[i]
  }
  return n
}
sum(1,2,3,4,5,6);//21
//若調(diào)用為一個(gè)數(shù)組
var a = [1,2,3,4,5,6]
sum.call(undefined,a[0],a[1],a[2]...)
更新用apply:
sum.apply(undefined,a);//21

七、bind

call 和 apply 是直接調(diào)用函數(shù),而 bind 則是返回一個(gè)新函數(shù)(并沒有調(diào)用原來的函數(shù)),這個(gè)新函數(shù)會(huì) call 原來的函數(shù),call 的參數(shù)由你指定。

八、return

每個(gè)函數(shù)都有 return

如果你不寫 return,就相當(dāng)于寫了 return undefined

九、柯里化 / 高階函數(shù)

返回函數(shù)的函數(shù)

* 柯里化:將 f(x,y) 變成 f(x=1)(y) 或 f(y=1)x
 //柯里化之前
  function sum(x,y){
      return x+y
  }
  //柯里化之后
  function addOne(y){
      return sum(1, y)
  }
  //柯里化之前
  function Handlebar(template, data){
      return template.replace('{{name}}', data.name)
  }
  //柯里化之后
  function Handlebar(template){
      return function(data){
          return template.replace('{{name}}', data.name)
      }
  }

柯里化可以將真實(shí)計(jì)算拖延到最后再做
關(guān)于柯里化的高級(jí)文章:

  1. http://www.yinwang.org/blog-cn/2013/04/02/currying
  2. https://zhuanlan.zhihu.com/p/31271179
* 高階函數(shù):

在數(shù)學(xué)和計(jì)算機(jī)科學(xué)中,高階函數(shù)是至少滿足下列一個(gè)條件的函數(shù):
a、 接受一個(gè)或多個(gè)函數(shù)作為輸入:forEach、sort、 map、 filter、reduce
b、輸出一個(gè)新函數(shù):bind、lodash.curry
fn.bind.call(fn,{},1,2,3)//
c、不過它也可以同時(shí)滿足兩個(gè)條件:Function.prototype.bind

高階函數(shù)用call的方式理解.png

[高階函數(shù)的應(yīng)用區(qū)別]https://blog.csdn.net/kingan123/article/details/79818566

偶數(shù)相加求和
array = [1,2,3,4,5,6,7,8]
var sum = 0;
for(var i= 0;i<array.length;i++){
  if(array[i] % 2 ===0){
    sum+=array[i]
  }
}
console.log(sum)
法一:array.filter(function(n){n%2===0});//[2,4,6,8]
        .reduce(function(prev,next){return prev+next})
法二:reduce(filter(array,function(n){n%2===0}),function(prev,next){return prev+next},0)
取奇數(shù)從小到大排序
array1 = [3,2,1,4,5,6,7,8]
sort(filter(array1,function(n){n%2===1}),function(a,b){return a-b})

接收一個(gè)函數(shù),叫高階函數(shù)
返回一個(gè)函數(shù),叫高階函數(shù)
函數(shù)被當(dāng)作參數(shù),叫回調(diào)
函數(shù)返回的函數(shù)參數(shù)比原函數(shù)少一個(gè)參數(shù)叫柯里化

十、回調(diào)

名詞形式:被當(dāng)做參數(shù)的函數(shù)就是回調(diào)
動(dòng)詞形式:調(diào)用這個(gè)回調(diào)
注意回調(diào)跟異步?jīng)]有任何關(guān)系

十一、構(gòu)造函數(shù)

返回對(duì)象的函數(shù)就是構(gòu)造函數(shù)
一般首字母大寫

new Number(1)//Number { 1 }
new String(1)
function Empty(){
    this.name = '空'
    return this //可不寫 
}
var empty = new Empty;//寫new,自動(dòng)返回 Empty.call({})

十二、箭頭函數(shù)

箭頭函數(shù)沒有this,

setTimeout(function(){
  console.log(this);//{name:'jack'}
}.bind({name:'jack'}),1000)
setTimeout(function(){
  console.log(this);//window
},1000)
setTimeout(function(){
  console.log(this);//{name:'jack'}
  setTimeout(function(){
    console.log(this);//window
  },1000)
}.bind({name:'jack'}),1000)

setTimeout(function(){
  console.log(this);//{name:'jack'}
  setTimeout(function(){
    console.log(this);//{name:'jack'}
  }.bind(this),1000)
}.bind({name:'jack'}),1000)
//箭頭函數(shù)
setTimeout(function(){
  console.log(this);//{name:'jack'}
  setTimeout((a)=>console.log(this),1000);//{name:'jack'}
}.bind({name:'jack'}),1000)

十三、閉包

如果一個(gè)函數(shù),使用了他范圍外的值,那么(這個(gè)函數(shù)+這個(gè)變量)就叫做閉包

var a = 1;
function f(){
  console.log(a)
}

https://zhuanlan.zhihu.com/p/22486908

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 函數(shù)和對(duì)象 1、函數(shù) 1.1 函數(shù)概述 函數(shù)對(duì)于任何一門語言來說都是核心的概念。通過函數(shù)可以封裝任意多條語句,而且...
    道無虛閱讀 4,961評(píng)論 0 5
  • 1.當(dāng)調(diào)用函數(shù)時(shí),除了傳入在定義中顯式聲明的參數(shù)之外,同時(shí)還傳入兩個(gè)隱式參數(shù),arguments 和 this。 ...
    悸動(dòng)無語閱讀 672評(píng)論 0 0
  • 原文鏈接 Haskell和scala都支持函數(shù)的柯里化,JavaScript函數(shù)的柯里化還與JavaScript的...
    dreamapple閱讀 2,668評(píng)論 0 24
  • 前言:本文將詳細(xì)的介紹JS中函數(shù)的相關(guān)概念(包括函數(shù)的call stack 、this 、作用域、閉包、柯里化、高...
    EnochQin閱讀 732評(píng)論 2 2
  • 我一直在等 等我忘了你 等我找回自己 等我放過自己 等你奔向光 奔向未來 等我再也無法出現(xiàn)在你的明天里
    七情九歌閱讀 418評(píng)論 0 0

友情鏈接更多精彩內(nèi)容