JavaScript 之 Function
1、函数的五种声明方式
1 | // 方式1:函数声明,存在变量提升 |
2、函数内部属性:name、length、this、arguments、callee、caller
- name(函数名)
- length(函数形参长度)
this
js 中的this
和 java、C# 中的类似,表示函数据以执行的的环境对象。
此外,这里还要注意一点的是,普通函数和 ES6 中的箭头函数中this
是有区别的。 - 普通函数中的this
是不固定的,它会随着执行环境的改变而改变; - ES6 中的箭头函数没有自己的this
, 箭头函数函数体内的this
就是定义时所在的对象,而不是使用时所在的对象,一旦它定义以后就不会再变;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15var color = 'red'
var obj = { color: 'blue' }
function sayColor() {
console.log(this.color)
}
sayColor() // red
obj.sayColor = sayColor
obj.sayColor() // blue
var sayColor2 = () => {
console.log(this.color)
}
sayColor2() // red
obj.sayColor2 = sayColor2
obj.sayColor2() // redarguments 与 callee
arguments
是一个伪数组对象,包含着传入函数中的所有参数。虽然它的主要用途是保存函数参数,但这个对象还有一个callee
属性,该属性是一个指针,指向拥有这个arguments
对象的函数。
下面是阶乘函数的定义,用到了递归,使用callee
很好的避免了函数内部的耦合:
1 | function factorial(num) { |
- caller
ECMAScript 5 规范化了另一个函数对象属性:caller
。这个属性保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,那么它的值为 null。
1 | fucntion outer(){ |
3、改变函数中 this 指向的三个方法:call、apply、bind
每一个函数都会从它的构造函数 Function
的原型中继承得到 call
、apply
、bind
三个方法。它们的用途在于在特定的作用域中调用函数,实际上等于改变函数内部 this
指针的指向(ES6 的箭头函数当然没用啦)。call
、apply
为立即调用函数而 bind
是返回函数。
apply
该方法接收两个参数,函数作用域对象、参数数组(数组或者 arguments 伪数组)call
call
方法和apply
方法作用完全相同,它们的区别仅在于接收的第二个参数形式不同。call
方法要求传递给函数的参数必须逐个列举出来。至于是采用call
还是apply
完全取决于你采取哪种传参方式方便。
1 | function sum(num1, num2) { |
事实上,传递参数并非 applay()
、call()
的真正用武之地,他们真正强大之处在于能够扩充函数赖以运行的环境。来看下面一个列子。
1 | window.color = 'red' |
使用 call()
或者 apply()
来扩充函数作用域的最大好处就是对象与方法的解耦。
- bind
bind
是 ES5 中定义的一个方法,bind
接受的参数跟call
一致,执行bind()
不会立即调用,它会生成一个新的函数,新函数的 this 就是 bind 方法穿进去的参数。例如:
1 | window.color = 'red' |
4、什么是闭包,闭包的用途是什么?
- 定义:「函数」和「函数内部能访问到的变量」(也叫环境)的总和,就是一个闭包。JavaScript 有两种作用域:全局作用域和函数作用域。函数内部可以直接读取全局变量。但是,在函数外部无法读取函数内部声明的变量。换言之,如果一个函数,使用了它范围外的变量,那么‘这个函数+这个变量’就叫做闭包。
示例
1
2
3
4
5
6
7
8
9
10function foo() {
var local = 1
function bar() {
local++
return local
}
return bar
}
var func = foo()
func()为什么要函数套函数呢?是因为需要局部变量,所以才把 local 放在一个函数里,如果不把 local 放在一个函数里,local 就是一个全局变量了,达不到使用闭包的目的——隐藏变量
- 用途
- 隐藏一个变量,外部无法直接访问这个变量
- 让这些变量始终保持在内存中
- 封装对象的私有属性和私有方法
1
2
3
4
5
6
7
8
9
10
11
12function f1(n) {
return function() {
return n++
}
}
var a1 = f1(1)
a1() // 1
a1() // 2
var a2 = f1(1)
a2() // 1
a2() // 2
//这段代码中,a1 和 a2 是相互独立的,各自返回自己的私有变量。
5、什么是 call stack
js 是单线程的,也就是说同一时间只能执行一个方法。
参考
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章