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中的函数与原型无关的地方就介绍完了,原型相关的内容在后面的文章介绍

明天再见~~

Javascript高级编程学习笔记(16)—— 引用类型(5) Function类型的更多相关文章

  1. Javascript高级编程学习笔记(10)—— 作用域、作用域链

    昨天介绍了,JS中函数的作用域 什么词法环境之类的,可能很多小伙伴不太明白. 在今天的内容开始之前,先做个简短的声明: 词法环境这一概念是在ES5中提出的,因为词法环境主要用于保存let.const声 ...

  2. Javascript高级编程学习笔记(18)—— 引用类型(7)单体内置对象

    什么是内置对象呢? js高级程序设计中给出的定义为:由ES规定不依赖于宿主环境的对象,这些对象在JS执行前就已经存在 前面我们介绍的引用类型都是内置对象 除了这些对象外ECMA还规定了两个单体内置对象 ...

  3. Javascript高级编程学习笔记(15)—— 引用类型(4)RegExp类型

    JS中处理字符串最常用的应该就是正则了 同样正则(RegExp)类型也是JS中引用类型的一种 ECMAScript通过 RegExp类型 来支持正则表达式 创建正则 var expression = ...

  4. Javascript高级编程学习笔记(17)—— 引用类型(6)基本包装类

    基本包装类 基本包装类这个概念或许有的小伙伴没有听说过 但是小伙伴们有没有想过,为什么基本数据类型的实例也有方法呢? 其实这些方法都来自基本包装类型 这是JS为了方便操作基础数据类型而创建的特殊引用类 ...

  5. Javascript高级编程学习笔记(14)—— 引用类型(3)Date类型

    除了前两天介绍的Object.Array类型,Date应该就是JS中最常用的引用类型了 先介绍一下Date类型,该类型使用在Java的 java.until.Date 类的基础上构建的 使用UTC 1 ...

  6. Javascript高级编程学习笔记(13)—— 引用类型(2)Array类型

    除了Object类型之外ECMA中最常用的引用类型可能就是Array类型了 并且ECMA中的数组类型和其他大多数编程语言的数组类型存在着很大的区别 今天就介绍一下JS中的Array的特别之处 区别 1 ...

  7. Javascript高级编程学习笔记(12)—— 引用类型(1)Object类型

    前面的文章中我们知道JS中的值分为两种类型 基础类型的值和引用类型的值 基础类型的值我已经大概介绍了一下,今天开始后面几天我会为大家介绍一下引用类型的值 Object类型 对象是引用类型的值的实例,在 ...

  8. Javascript高级编程学习笔记(3)—— JS中的数据类型(1)

    前一段时间由于事情比较多,所以笔记耽搁了一段时间,从这一篇开始我会尽快写完这个系列. 文章中有什么不足之处,还望各位大佬指出. JS中的数据类型 上一篇中我写了有关JS引入的Script标签相关的东西 ...

  9. Javascript高级编程学习笔记(97)—— WebGL(3) WebGL上下文(1)

    WebGL上下文 在支持WebGL的浏览器中,WebGL的名字为 "experimental-webgl",这是由于 webgl 的规范仍未制定完成 制定完成后名字就会改为简单的 ...

随机推荐

  1. Sublime Text 执行后只有运行时间,没有执行结果!解决方法!

    问题:build完python代码,只输出:[Finished in 0.2s] 分析:操作回忆:开始是可以看到运行结果的,后来在Tools>>Build with 选择了"Sy ...

  2. WPF中的数据绑定(初级)

    关于WPF中的数据绑定,初步探讨 数据绑定属于WPF中比较核心的范畴,以下是对WPF中数据绑定的一个初步探讨.个人感觉还是带有问题性质的叙述比较高效,也比较容易懂 第一,什么是数据绑定? 假定有这么一 ...

  3. OAuth2.0 协议的理解

    OAuth(Open Authorization)协议就是为用户资源的授权提供了一个安全.开放.简易的标准. OAuth在第三方应用与服务提供商之间设置了一个授权层,第三方应用通过授权层获取令牌,再通 ...

  4. Python中安装bs4后,pycharm依然报错ModuleNotFoundError: No module named 'bs4'

    学习网络抓取时,第一步出现问题. 执行示例代码 from urllib.request import urlopen from bs4 import BeautifulSoup html = urlo ...

  5. Google资深工程师深度讲解Go语言完整教程

    资源获取链接点击这里 欢迎大家来到深度讲解Go语言的课堂.本课程将从基本语法讲起,逐渐深入,帮助同学深度理解Go语言面向接口,函数式编程,错误处理,测试,并行计算等元素,并带领大家实现一个分布式爬虫的 ...

  6. C/C++生成静态库动态库及语言交互

    C++静态库与动态库(比较透彻) Go中调用C的动态库与静态库 我的示例 文件结构 |- sample |- c |- libsample |- libsample.h |- libsample.cp ...

  7. vue2组件懒加载浅析

    vue2组件懒加载浅析 一. 什么是懒加载 懒加载也叫延迟加载,即在需要的时候进行加载,随用随载. 二.为什么需要懒加载 在单页应用中,如果没有应用懒加载,运用webpack打包后的文件将会异常的大, ...

  8. 【Selenium】【BugList7】执行driver.find_element_by_id("kw").send_keys("Selenium"),报错:selenium.common.exceptions.InvalidArgumentException: Message: Expected [object Undefined] undefined to be a string

    [版本] selenium:3.11.0 firefox:59.0.3 (64 位) python:3.6.5 [代码] #coding=utf-8 from selenium import webd ...

  9. ntelliJ IDEA 仿照vs2017快捷键设置,以及字体颜色设置

    因后期工作需要使用java技术栈,所以近期抽空下载了intelliJ IDEA工具,但是作为一个Net开发者,在使用了vs以后,感觉在使用别的开发工具感觉就是没法和vs相比,毕竟vs被称为宇宙最强id ...

  10. iOS模拟器:Undefined symbols for architecture x86_64

    描述:为了适配iPhone 5s的64位处理器,在编译选项中加入了arm64架构.但是发现工程在真机上可以编译通过但是在模拟器上却未编过. 问题解决:经研究在编译选项中再加入x86_64架构,重新编译 ...