五种声明
具名函数
function add (a, b) {
return a + b
}
匿名函数
let add = function (a, b) {
return a + b
}
两边都有名字
和上面的方法有不一致性
let add = function x (a, b) {
console.log(x) // 可以访问x,是一个函数
return a + b
}
console.log(x) // 报错
window.Function 函数对象
new Function('a', 'b', 'return a + b')
箭头函数
let fn = (a, b) => a + b
函数的name属性
function f() {}
console.log(f.name) // f
let f2 = function() {}
console.log(f2.name) // f2
let f3 = function f4() {}
console.log(f3.name) // f4
console.log(f4.name) // 报错
let f5 = new Function()
console.log(f5.name) // anonymous -> 函数就是叫做匿名的"anonymous"
let f6 = () => {}
console.log(f6.name) // f6
体系
call()
可以调用的对象就是函数
let f = {
params: ['x', 'y'],
fbody: 'console.log(1)',
call: function() {
return eval(f.body)
}
}
f.call()
// f 是这个函数对象, f.call() 就是执行函数体
f(1, 2) vs f.call(undefined, 1, 2)
- f(1, 2) 是语法糖
- f(undefined, 1, 2) 才是真正的函数调用
function f(x, y) {
return x + y
}
f.call(undefined, 1, 2) // 3
this & arguments
- call 的第一个参数可以用this得到
- call 的第二个参数可以用arguments得到
f.call(this, arguments)
this
- 如果开启严格模式,那么第一个参数传什么,this就是什么
- 如果不开启严格模式
- 第一个参数如果是基本类型会转成对象,如 1 -> Number的1, ‘str’ -> String 的 str
- 而如果本来就是对象Object,那么还是那个对象
- 如果第一个参数是undefined会变成全局变量
'use strict'
function f() {
console.log(this) // undefined / 不是严格模式就是全局对象
console.log(arguments) // [1, 2, 3]
}
f.call(undefined, 1, 2, 3)
arguments
- Arguments是一个伪数组,判断是否是一个伪数组
- 没有数组的共有属性和方法
__proto__ =? Array.prototype
闭包
如果一个函数使用了范围外的值,那么这个函数+这个变量叫做闭包
var a = 1
function f4() {
console.log(a)
}
历史原因
为什么要有this
- 把
call()
的第一个参数放this,[2, 3]
作为arguments - JS 没有class