task27 进阶:JS 核心之函数!!!重要

  1. 函数的 5 种声明
  2. 如何调用函数 f.call
  3. this 和 arguments
  4. 什么是 call stack
  5. 作用域
  6. 闭包

如果你意犹未尽,可以查看我的《JS深入浅出》里讲的《函数》

函数的 5 种声明

  1. 具名函数

     function x(input1,input2){
         return input1+input2
     }
     x.name // 'x'
     console.log(x)  
     //如果x是字符串,直接打印x
     //如果x不是字符串,调用x.toString()
    

输入:x,y
返回:写在return后面,如果不写,自动return undefined


image.png
  1. 匿名函数

     var f
     f = function(x,y){
         return x+y
     }
     f.name // 'f'
    
    

如果使用匿名函数,必须要把这个匿名函数赋值给一个对象

  1. 具名函数赋值

     var f
     f = function f2(x,y){ return x+y }
     f.name // 'f2'
     console.log(f2) // undefined
    
    
image.png

image.png
function y(){}
console.log(y)  //√
//刷新下页面
var x = function y(){}
console.log(y)  //× 报错
  • 面试中经常问第3种
  1. window.Function

     var f = new Function('x','y','return x+y')
     f.name // "anonymous"
    
var n=1
var f = new Function('x','y','return x+'+n+'+y')
f(1,2)  //返回结果是多少?4还是'1n2'?
image.png
  1. 箭头函数

     var x = (x,y) => {
         return x+y
     }
     var sum = (x,y) => x+y 
     //如果{}里面只有一句话,且这一句话是return,
     //那么可以把{}和return一起去掉。必须一起去掉
     //等价于var sum = (x,y) => {return x+y} 
    
     var n2 = n => n*n
     //如果参数只有一个,()可以省略掉
    
    

函数的name属性

image.png

如何调用函数

f.call(asThis, input1,input2)
其中 asThis 会被当做 this,[input1,input2] 会被当做 arguments
禁止使用 f(input1, input2),因为学会 .call 才能理解 this

函数是一段可以反复调用的代码块。函数还能接受输入的参数,不同的参数会返回不同的值。

image.png

image.png

image.png

eval()传的参数是一个字符串,eval将这段字符串当做代码执行
函数是一个对象,函数执行就是eval函数体的过程


image.png

image.png

f是这个对象,f.call()是执行这个函数的函数体

函数是一个对象,这个对象可以执行一段我们写的代码


image.png
  • js有7种数据类型
  • 6种简单数据类型:number,string,boolean,undefined,null,symbol
  • 1种复杂数据类型Object,原型链中有Object.prototype的都是对象
  • Array,Function,Date,RegExp,Error等都属于Object类型,因为他们的原型链中有Object.prototype。
  • Array有自己独有的原型Array.prototype
  • Function有自己独有的原型Function.prototype
  • Function.prototype有三个很重要的方法:call() apply() bind()


    image.png

    以后不准用f(1,2)这样调用函数,要用f.call(undefined,1,2)!!!!

this 和 arguments

function f(){
    'use strict'
    console.log(this)
    console.log(arguments)
    return undefined
}
f.call(1,2,3) // this 为 1,arguments 为 [2,3]

  1. call的第一个参数可以用this得到
  2. call的第一个参数后面的参数可以用arguments得到(arguments是一个伪数组)
  3. 在普通模式下,如果this为undefined,那个浏览器会把this转换为window
  4. 在严格模式下('use strict'),传的是什么,this就是什么。this是call的第一个参数


    image.png
严格模式.png

js中的new和this看起来没什么必要用,是有历史原因的,但是设计js的时候公司的要求是长得像java


image.png
伪数组.png

伪数组:长得像数组,但是原型链中没有Array.prototype。不可以使用push()、pop()这些数组的方法

什么是 call stack

stack:栈(先进后出)
调用栈:每进入一个函数,会把这个函数的位置记录到栈里面。等回来的时候直接就回到栈最上面的那个位置


图片
function sum(n){
  console.log(n)
  if(n==1){
    console.log('return 1')
    return 1
  }else{
    console.log(`return ${n} + sum.call(undefined,${n-1})`)
    return n + sum.call(undefined, n-1)
  }
}
sum.call(undefined,5)
//sum(5)  //5+sum(4)
//sum(4)  //4+sum(3)
//sum(3)  //3+sum(2)
//sum(2)  //2+sum(1)
//sum(1)  //1
image.png

可以打断点,在控制台看call stack↓


image.png

但是这个栈是有上限的,太多的栈会爆掉的 stack overflow(栈溢出)


image.png
image.png

stack overflow

作用域

  • 按照语法树,就近原则
  • 我们只能确定变量是哪个变量,但是不能确定变量的值


    语法树.png

    就近原则.png

    找当前作用域有没有这个变量的值,没有就向上一层找有没有,采取就近原则

//请分别说出每个位置的a是什么值?
var a = 1
function f1(){
  var a = 2
  f2.call()
  console.log(a)
  function f2(){
    var a = 3
    console.log(a)
  }
}
f1.call()
console.log(a)

题1

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

拿到代码直接做——必然会错。请先提升声明!!!
变量提升!!!
等价于↓

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

答案是:undefined

题2

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

拿到代码直接做——必然会错。请先提升声明
答案是:1
题3

var liTags = document.querySelectorAll('li')
for(var i = 0; i<liTags.length; i++){
    liTags[i].onclick = function(){
        console.log(i) // 点击第3个 li 时,打印 2 还是打印 6?
    }
}

拿到代码直接做——必然会错。请先提升声明


image.png

闭包

  1. 搜索:方应杭 闭包
  2. 看文章
//这个就是闭包
var a = 1
function f4(){
  console.log(a)
}
//如果一个函数,使用了它范围外的变量,那么(这个函数+这个变量)就叫做闭包
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,239评论 0赞 2
  • var navigator = navigator || {};var window = window || {}...
    DF_Sky阅读 1,613评论 0赞 0
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 14,369评论 0赞 38
  • 函数只定义一次,但可能被执行或调用任意次。JS函数是参数化的,函数的定义会包括一个称为形参的标识符列表,这些参数在...
    PySong阅读 732评论 0赞 0
  • 曾经的我特别害怕人,害怕成为众人焦点,害怕被讨论,害怕别人不喜欢我,害怕别人的评价不过是鼓励抑或欺骗。害怕与人交流...
    角落蜷缩阅读 308评论 0赞 0

友情链接更多精彩内容