JS 里的函数

作者: 小志1 | 来源:发表于2018-03-20 19:55 被阅读0次

    讲函数前,先了解Function和function的区别。

    • function是关键字(if else var )function声明一个函数 function f(){}
      Function是全局对象 new Function('x','y','return x+y',) 或者 Function('x','y','return x+y')

    声明函数有两种方法1.关键字声明 2.new Function声明
    1.具名函数 function f(){ return undefined} 2.匿名函数 var f f = function(){} 这两个属于第一种
    3.new Function('x','y','return x+y ') 这个属于第二种(除非无聊或者想用字符串拼凑的时候才有这种)

    函数的五种声明方式

    1. function f(x,y){ return x+y }
    2. var f = function (x,y){ return x+y }
    3. var f = function x(x,y){ return x+y }
    4. var f = new Function('x','y','return x+y') // window.Function
    5. var f= (x,y) => { return x+y }//es6的箭头函数
      var f = (x,y) => x+y //return和花括号一起省略
      var f = n => n*n //参数只有一个时,参数的括号可以省略

    name知识点

    每个函数都有名字,但是比较鸡肋,基本用不到

    function f(){}  
    f.name     //     f
    var f2 = function(){}
    f2.name    //    f2
    var f3 = function f4(){}
    f3.name    //    f4
    f4.name    //    f4 is not defined
    f5 = new Function('x','y','return x+y ')
    f5.name    //    anonymous
    

    函数是可以反复调用的代码块 调用函数英文是call

    call

    var f = {}
    f.params = ['x','y']
    f.functionBody = 'console.log("fff")'
    f.call = function (){
        return window.eval(f.functionBody)
    }
    f.call()  //    fff
    
    call
    call其实就是函数的复杂写法 f(1,2) === f.call(undefined,1,2),实际参数从第二个开始传,undefined是this , 1,2是arguments
    call的第一个参数可以用this得到,call后面的参数可以用arguments得到
    f和的区别 f是函数体 f.call()指向这个对象的函数体
    call

    其中可以执行代码的对象就叫函数(我们写的代码)

    函数原型Function.prototype有三个重要的方法call apply bind,会重写toString方法覆盖Object的toString方法

    this

    在普通模式下,如果this是undefined,浏览器会自动把this变成window

      f = function (){
         console.log(this == = window)
      }
      f.call(undefined)  // true
    

    如果是严格模式,给undefined打印出的就是undefined,

      f = function (){
         'use strict'
         console.log(this === window)
      }
      f.call(undefined)  //false
    

    arguments

    argument是伪数组,因为它的原型链上没有Array.prototype,或者 proto没有指向Array.prototype
    下面判断

    f = function(){
        arguments.push(4)
        console.log(arguments)
    }
    f.call(undefined,1,2,3)   
    

    会报arguments.push is not a function的错,所以是伪数组
    很好判断是不是伪数组,给push方法

    call stack 调用栈

    Stack Overflow 和中国的segment fault 这两个网站的由来就是从栈溢出而来的

    function sum(n){
        if(n==1){
            return 1
        }else{
            return n + sum.call(undefined, n-1)
        }
    }
    sum.call(undefined,9650)  //46566075
    

    再大就栈溢出Maximum call stack size exceeded,所有栈的调用最多在9650左右,再多就栈溢出了

    call stack

    作用域

    在使用变量的时候 ,怎么去找它的声明 ,就找这个作用域里面的声明,找不到找外面作用域的声明,如果还找不到 。再往外面找,就近原则
    声明提升:变量提升,函数的声明也提升,先提升在看代码

    f1里的console.log是什么

    var a = 1
    function f1(){
        f2.call()
        console.log(a)    //undefined
        var a = 2
        function f2(){
            var a = 3
            console.log(a)
        }
    }
    f1.call()
    console.log(a)   
    //3 
    //undefined 
    //1
    

    变量提升改写代码

    var a = 1
    function f1(){
        var a
        function f2(){
            var a
            a = 3
            console.log(a) // a定义再赋值在console.log前面,所以是3    }
        f2.call()
        console.log(a)  // a先定义,赋值在console.log下面,所以是undefined
        a = 2
    }
    f1.call()
    console.log(a)
    

    例2
    f4打印的是什么

    var a = 1
    function f1(){
        console.log(a)
        var a = 2
        f4.call()
        
    }
    function f4(){
        console.log(a)     //1, f4的a 一定是f4的作用域或者它的父作用域  
    }
    f1.call()
    console.log(a)
    

    f1的a只在f1函数里有效,而f4的a 一定是f4的作用域或者它的父作用域 ,不用和上面的变量提升搞混

    例3
    ????里的内容有没有可能是的a输出的不是1

    var a = 1
    function f4(){
        console.log(a)
    }
    ???????   //a =  2   不是立刻执行就可能是2
    f4.call()
    

    作用域说的是a是那个a,但并没有说a是哪个a的值,如果????里设置了延时代码,那么a就不一定是1了

    闭包

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

    这就是闭包 如果一个函数,使用了它范围外的变量,那么(这个函数+这个变量)就叫做闭包

    相关文章

      网友评论

        本文标题:JS 里的函数

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