美文网首页
JS专题: 函数

JS专题: 函数

作者: squall1744 | 来源:发表于2018-04-20 15:54 被阅读0次

函数声明


匿名函数

var fn = function() {
  return 1
}

var fn2 = fn
fn.name // fn
fn2.name //fn

具名函数

// fn3在全局作用域下
function fn3() {
  return 3
}

//fn4作用域在函数体内
var fn5 = function fn4() {
  return 4
}
console.log(fn4) //not defined

箭头函数

var fn6 = () => {
  return 6
}

词法作用域


我们有如下代码

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)
     }
 }

对于上面的代码, 浏览器先把代码变成抽象语法树


词法树

假设我们要在fn2中调用local1变量

  1. 解析器会先在fn2节点中找, 上图中我们发现, fn2节点内没有local1
  2. 在fn2节点的上层节点中继续找, 也就是在fn1节点中找, 发现了local1
  3. 调用fn1中的local1
  4. 假设fn1中还没有, 那就继续往上找, 知道咋window下还找不到, 就报错
  5. 词法书只是分析调用哪个变量, 并不是分析变量的值

对于上面的第五点, 我们具体说明一下什么叫分析变量, 并不分析变量的值

假如我们有如下代码, 调用b()之后函数的值为1

var a = 1
function b() {
  console.log(a)
}
b() //1

我们稍在函数中给a赋值, 这时候打印出来的就是2

var a = 1
function b() {
  a = 2
  console.log(a)
}
b() //2

这就说明了词法树只会分析函数调用时候调用的是哪个变量, 并不关心变量的值, 变量的值决定于你给它赋值是多少

Call Stack


这里还是提一下loupe, 这个很清晰的描述了调用栈

this & aguments


  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]

从上面的代码就能看出, f()这种方式的调用, 就是隐藏了this的简化版的call()

  • this 为什么必须是对象

因为 this 就是函数与对象之间的羁绊

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 的第一个参数
      // this 是参数,所以,只有在调用的时候才能确定
      person.sayHi.call({name:'haha'})  // 这时 sayHi 里面的 this 就不是 person 了
      // this 真的很不靠谱

      // 新手疑惑的两种写法
      var fn = person.sayHi
      person.sayHi() // this === person
      fn()  // this === window

call / apply
fn.call(asThis, p1,p2) 是函数的正常调用方式
当你不确定参数的个数时,就使用 apply
fn.apply(asThis, params)
bind
call 和 apply 是直接调用函数,而 bind 则是返回一个新函数(并没有调用原来的函数),这个新函数会 call 原来的函数,call 的参数由你指定。
return
每个函数都有 return
如果你不写 return,就相当于写了 return undefined

柯里化和高阶函数


  • 柯里化:将 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)
      }
  }

柯里化可以将真实计算拖延到最后再做
关于柯里化的高级文章:

  1. http://www.yinwang.org/blog-cn/2013/04/02/currying
  2. https://zhuanlan.zhihu.com/p/31271179
  • 高阶函数
    在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:

    接受一个或多个函数作为输入:forEach sort map filter reduce
    输出一个函数:lodash.curry
    不过它也可以同时满足两个条件:Function.prototype.bind

下面两个例子就是高阶函数在前端的应用例子

// 筛选出数组中的偶数并求和
reduce(filter(array, function(n){ n % 2 === 0}), function(prev, next){return preve+next},0)

//筛选出数组中的基数并排序
sort(filter(array, function(n){n % 2 === 1}),function(a,b){return a-b})

在前端, 高阶函数和函数式编程在react中有大量应用

回调


回调
分为两部分

  1. 函数被当做另一个函数参数
  2. 在函数中调用这个函数参数
    回调跟异步没有任何关系

相关文章

  • 【基础系列】JS使用技巧专题

    JS使用技巧专题 1开发技巧 1.1函数使用 1.1.1函数声明方式 JS函数的写法总结 http://blog....

  • JS专题: 函数

    函数声明 匿名函数 具名函数 箭头函数 词法作用域 我们有如下代码 对于上面的代码, 浏览器先把代码变成抽象语法树...

  • JS函数专题

    函数编写 JS的函数可以嵌套(骚不骚?但是好像其他语言也支持?) 变量提升JavaScript的函数定义时,它会先...

  • JavaScript 05 函数

    js函数的概念和作用,js函数的定义,js函数的调用,js事件驱动的概念,js函数的实参和形参,js的作用域,js...

  • js 深入

    * js语法* js的动态函数和匿名函数* js动态函数Functionnew Function();* 匿名函数...

  • JS专题系列之惰性函数与记忆函数

    一、惰性函数 惰性函数:顾名思义就是懒惰的函数,举一个简单的例子,如果我们需要判断当前浏览器是哪一种浏览器,我们需...

  • 2018-12-01

    js中括号操作属性 js函数 js换肤 变量和函数预解析 匿名函数 函数传参 函数return关键字 流程控制语句...

  • jQuery入口函数的作用以及jQuery入口函数和js入口函数

    jQuery的入口函数 js和JQuery入口函数的区别 JS入口函数和JQuery入口函数

  • 微信小程序本地和云函数方式获取云存储数据

    本地方式 js代码 云函数方式 js代码 云函数代码

  • JS操作属性、函数

    JS操作style属性 JS操作class属性 函数 匿名函数 函数传参 作业 if练习 switch练习

网友评论

      本文标题:JS专题: 函数

      本文链接:https://www.haomeiwen.com/subject/znbakftx.html