函数
:::info
在JS中,函数是对象,能和其他值类型一样,可以赋值给变量,也可以作为函数的返回值。
在C语言中,函数实体比其他的值实体低一级,函数作为子程序只能被调用,而不能有函数表达式或者函数赋值给变量。
:::
写函数:
- 考虑函数定义方式
- 输入、输出
- 观察周围的词法环境记录。注意动态环境记录项:this、arguments、new.target
- 写逻辑算法
函数定义
箭头函数
lambda函数、匿名函数。
:::info
匿名函数就是函数没有名字,说明匿名函数不需要通过函数名复用,仅仅作为代码片段,能够快速插入代码片段,十分方便。
:::
IIFE
ES6已经被淘汰的语法,了解即可。IIFE主要是利用函数作用域,模拟块级、模块作用域。但是ES6提供内置语法实现块作用域、模块化。
/**
* IIFE中是匿名函数,函数名写不写是一样的。因为函数表达式执行完后,函数就被销毁,函数不需要复用。
*/
(function () {
for(var i = 0; i < 2; i++){
console.log(i);
}
})();
//IIFE 第二种写法,W3C推荐写法
(function () {
for(var i = 0; i < 2; i++){
console.log(i);
}
}());
//IIFE另一种语法
+ / - / ! / 0 || / 0 && function (){} (); //在函数前加上运算符也会将函数转化为IIFE
//面试题中特殊的写法
function add(a){ //这里不能使用匿名函数
console.log(a)
}(2); //因为这里传了值,JS引擎不会认为这是IIFE语法错误。JS引擎会判断为这是一个函数声明和一个没有实际含义的表达式(2);最终不会报错。
//注意一种语法错误写法,函数执行符号()前面一定是表达式
function add() {
console.log(1);
}(); //()前面不是表达式,而是函数声明,不能直接调用执行。(指针)函数名 +()+ ; 函数才能调用执行。
函数执行上下文
函数在执行时,除了周围嵌套的词法环境(作用域)以外,还会创建函数本身的词法环境,包含有几个的隐藏环境项(arguments、this、new.target),这些环境项在函数执行期间动态确定。
arguments
ES6之前arguments对象主要解决收集可变参数长度的问题,ES6有了…运算符,arguments对象就被淘汰,直接使用命名参数。箭头函数在ES6标准中已经取消支持arguments对象。
//非严格模式,参数没有默认值,arguments和形参在更改值的时候会同步。
function sum(a, b) {
a = 12;
console.log(arguments[0]); //12
arguments[0] = 10;
console.log(a); //10
}
sum(1, 2);
//严格模式中arguments和命名形参不会同步
function sum(a, b) {
"use strict";
a = 12;
console.log(arguments[0]); //1
arguments[0] = 10;
console.log(a); //12
}
sum(1, 2);
//形参使用默认值时arguments的行为自动切换为严格模式。
function foo(a = 1) {
a = 2;
console.log(arguments[0]); //42
}
foo(42);
:::info
非严格模式,形参和实参arguments相互之间产生同步,语义不明确。(不要使用)
严格模式,形参和实参互不影响,语义也更加明确。(模块作用域、形参默认值都会使函数切换为严格模式)
:::
this
函数中的this
普通函数内使用this没有意义。 :::info
- 非严格模式,this指向的是window对象。
- 严格模式,函数内没有设置this,this指向的是undefined。
:::
方法中的this
this指向的是调用该方法的上下文对象。 :::info this实际应用就是基于对象中的方法。这一点也可以说是函数和方法的本质区别,方法的执行上下文中隐含有this。 :::箭头函数中的this
:::info 箭头函数没有this,会在函数定义时确定,找上一级作用域中的this。 ::: ```javascript var obj = { count : 10, doSomethingLater : function (){
} }setTimeout(function(){ //异步函数中的函数参数,是在window对象中执行。
this.count++;
console.log(this.count);
}, 300);
var obj = {
count : 10,
doSomethingLater : function(){
setTimeout( () => { //上一级作用域就是方法doSomethingLater中的this
this.count++;
console.log(this.count);
}, 300);
}
}
var obj = { i: 10, b: () => console.log(this.i, this), //上一级作用域是window c: function() { console.log(this.i, this); } } ```
new.target
检测函数是否使用new关键字调用。
- 是:指向构造函数
- 不是:undefined