zoukankan      html  css  js  c++  java
  • Javascript高级编程学习笔记(16)—— 引用类型(5) Function类型

    JS中许多有趣的地方都和函数脱不了联系

    那么是什么让JS中的函数这么有趣呢?

     我们一起来看看吧

    Function类型

    在JS中函数实际上就是对象,每个函数都是Function类型的实例,和JS的其他引用类型都拥有属性和方法

    正是由于这个原因,函数名实际上就是一个指针,指向函数对象,并不会与函数绑定

    函数的声明

    创建一个函数一般来说有下面几种方法

    // function关键字声明
    function sayHello(){
        alert("hello");
    }
    
    // 函数表达式
    var sayHello = function(){
        alert("hello");
    }
    
    // 构造函数
    var sayHello = new Function("alert('hello')");// 接收任意数量参数,最后一个参数为函数体

    其中最少使用的就是最后一种,因为这种方式会导致JS解析两次代码

    而对于function 和 表达式这两种方式来说,区别在于(在ES6以下)function声明会在创建执行环境阶段完成,而表达式会在代码执行阶段创建函数;

    简单地说function声明的函数会比,函数表达式更早的创建函数(在代码执行之前)

    PS. 由于函数名仅仅只是指向函数的指针,所以一个函数可以有多个函数名

    没有重载

    之前的文章中,我提到了JS的函数没有重载

    这一切的根源就是:JS中的函数名只是一个指针,而不是一个函数签名

    所以当我们在JS中声明同名函数的时候,实际上就是让已经指向一个函数的指针指向另外一个函数,自然也就不能实现重载了

    变量提升

    变量提升,以及闭包等概念,在许多公司前端面试的时候经常会考到

    这里撇开闭包不谈,先来说一下变量提升

    变量提升这一概念只存在于ES6以下的ES语法中

    前面讲JS执行环境的时候我详细解释了这一过程

    什么是变量提升?

    说白了变量提升就是:当JS在执行到声明变量的语句之前就可以访问该变量了

    对于函数之外的变量,变量提升虽然可以在声明语句前访问到该变量,但是由于赋值语句尚未执行,所以只能访问到 undefined

    在上方的例子中我们看到变量a就在声明语句前被我们访问了,而变量 b 我们没有声明所以js报错

    而对于函数来说,函数的变量提升,我们甚至可以在函数声明前就访问到函数的函数体

    而变量提升的原理就是,JS的执行环境的创建,具体过程见下图:

    所以var声明的变量在,语句执行前就已经被js引擎设置了值,而ES6的let,const在创建执行环境时并不会为这些变量设置值,所以也就不存在变量提升

    而由于函数表达式是在代码执行阶段才会执行,所以函数表达式创建的函数并不能在声明语句前访问

    我也不知道我讲清楚没,没懂的小伙伴可以留言,有错的地方也欢迎大家留言指出

    函数作为函数返回值

     在JS中由于函数本就是一个对象,自然也可以作为函数的返回值返回

    这种情况适用于使用的函数需要根据参数的类型、值等调用不同的函数的情况

    函数内部属性

    函数的内部有两个特殊的对象:

    1.this

    2.arguments

    其中 this 对象指向的是当前函数的执行环境对象

    而arguments用于保存函数的参数

    arguments对象有个callee属性,指向当前函数本身

    通过arguments可以实现更加安全的递归调用

    var test = function(num){
        if(num===1){
            return ; 
        }
        return num * arguments.callee(num-1);
    }

    这种方式可以避免当函数名改变时导致的递归报错

    然而为了安全性,在严格环境下无法使用

    所以严格环境可以使用下面的代码来实现该功能

    var test = function lhy(num){
        if(num===1){
            return ; 
        }
        return num * lhy(num-1);
    }

    除此而外函数实例上还有一个属性 caller

    用于保存调用当前函数的函数的引用,全局环境下该值为 null

    函数属性和方法

    每个函数都包含以下两个属性:

    1.length  表示函数希望获得参数的个数

    2.prototype 跟原型链相关,在此不过多介绍

    除了上述方法之外,函数还包括3个非继承而来的方法

    1.applay()

    2.call()

    3.bind()

    这三个方法的作用十分类似,都是用于改变函数的 this 指向

    其中 applay 和 call 都是改变指向并执行,而 bind 只改变函数指向并不会立即执行(只接收一个参数即要绑定的对象)

    而apply和call的第一个参数都是this指向的对象,区别在于:

    call方法的的参数必须一一例举

    而apply只需要接收两个参数,第二参数是参数数组

    所以使用时要视具体情况而定

    JS中的函数与原型无关的地方就介绍完了,原型相关的内容在后面的文章介绍

    明天再见~~

     

  • 相关阅读:
    java将pdf转成base64字符串及将base64字符串反转pdf
    input校验不能以0开头的数字
    js校验密码,不能为空的8-20位非纯数字或字母的密码
    tomcat正常关闭,端口号占用解决 StandardServer.await: create[8005]:
    Eclipse中项目报Target runtime com.genuitec.runtime.generic.jee60 is not defined异常的解决
    Access restriction: The type Base64 is not accessible due to restriction on
    [操作系统] 线程和进程的简单解释
    ssh登录一段时间后断开的解决方案
    [SAMtools] 常用指令总结
    [C] 有关内存问题
  • 原文地址:https://www.cnblogs.com/lhyxq/p/10141880.html
Copyright © 2011-2022 走看看