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

2019-05-30  本文已影响0人  vivienYang2019
  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)  //× 报错
  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

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

作用域

//请分别说出每个位置的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)
}
//如果一个函数,使用了它范围外的变量,那么(这个函数+这个变量)就叫做闭包
上一篇 下一篇

猜你喜欢

热点阅读