你真的懂函数吗
函数声明
匿名函数 就是声明的时候不给名字
function(){ return 1 ;} 你声明了它 但是又不能引用到它
1 | // function(){ return 1 ;} 匿名函数 相当于废话 会报错 你只有给了引用才能使用 |
具名函数
1 | function fn3(){ |
将具名函数赋值给一个变量 它的作用域就变了
1 | var fn4 = function fn5(){return 1;} |
全局作用域的函数 赋值给变量他的作用域不受影响
1 | function fn6(){return 1;} |
箭头函数
1 | var fn8 = ()=>1; //无参数 返回1 |
fn1 调用的时候不会立即执行
而是会生成一个抽象语法树
校验里面的每句话 如果有错误就停止执行
没错再从头开始执行
词法作用域
一个函数能访问那些变量 在做词法分析的时候就确定了
词法树分析的是语义
只能确认a就是这个函数内部的a
不能确定的是“值”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 var global = 1;
function fn1(param1){
var local1 = 'local1';
var local2 = 'local2';
function fn2(param2){
var local2 = 'fn2 local2';
console.log(local1);
console.log(local2);
}
function fn3(){
var local2 = 'fn3 local2';
fn2(local2);
}
}
经典面试题
1 | var a = 1; |
你在看看
1 | var a =1; |
词法作用域只能确定这个a是不是那个a,不能确定a的值是不是那个值
call stack 调用栈
以后再更新。。。(没人考)
this & arguments
重要[参考链接]
(https://zhuanlan.zhihu.com/p/23804247)this 是隐藏的第一个参数,且必须是对象
- call的第一个参数就是this
- call的第的哥参数后面的就是arguments(伪数组)
- fn() 等同于 fn.call()
- 非严格模式下,fn()和fn.call() this会转变为window
- fn()是阉割版的fn.call()
1 | function f(){ |
尽可能避免使用fn()的调用形式,因为会让你产生不知道this是谁的恐慌
- this 为什么必须是对象
因为 this 就是函数与对象之间的羁绊
1 | // 第一步思考 |
1 | // 第二步思考 |
person.sayHi() 等价于 person.sayHi(person)
fn() 等价于 fn.call()
call / apply
- 第一原则call的第一个参数是this
- apply是另一版本的call
apply的使用场景就是在你不知道要传递的参数有多少个的情况
1 | fn.call(asThis, p1,p2) 是函数的正常调用方式 |
bind
call 和 apply 是直接调用函数,而 bind 则是返回一个新函数(并没有调用原来的函数),这个新函数会 call 原来的函数,call 的参数由你指定。
待更新。。。。。
柯里化
返回函数的函数
柯里化:将 f(x,y) 变成 f(x=1)(y) 或 f(y=1)x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//柯里化之前
function sum(x,y){
return x+y
}
//柯里化之后
function addOne(y){
return sum(1, y)
}
//柯里化之前
function Handlebar(template, data){
return template.replace('{{name}}', data.name)
}
//柯里化之后
function Handlebar(template){
return function(data){
return template.replace('{{name}}', data.name)
}
}柯里化可以将真实计算拖延到最后再做
关于柯里化的高级文章:
柯里化唯一的好处就是惰性求值
高阶函数:
在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:
接受一个或多个函数作为输入:forEach sort map filter reduce
1 | //接收一个函数 |
- 输出一个函数:lodash.curry
- 不过它也可以同时满足两个条件:
- Function.prototype.bind
高阶函数的好处就是任意组合
1 | var arr = [1,2,3,4,5,6,7,8]; |
回调函数
- 名词形式:被当做参数的函数就是回调
- 动词形式:调用这个回调
- 注意回调跟异步没有任何关系
构造函数
- 返回对象的函数就是构造函数
- 一般首字母大写
1 | var n = new Number(1) |
箭头函数
1 | function fn(x,y){ |
箭头函数没有this
1 | setTimeout(function(){ |
箭头函数干掉了this
1 | setTimeout(function(){ |
js的漏洞 function(){} 等价于 function(){}.call()
call的第一个参数就是this
call不传递参数就是window
强迫症就是要给箭头函数加this?
答案是不行 会被忽略
1 | var fn =()=>{console.log(this)} |