- 作用域
- 作用域分类
- LHS&RHS
- 声明提升
- 变量提升
- 函数
- 函数定义
- 箭头函数
- 函数名
- 函数参数
- 函数提升
作用域:
众所周知,js作用域分为两类:全局作用域和局部(函数)作用域。
- 全局作用域:即在
script
定义的变量。 - 局部作用域:在函数内部定义的变量。
js规定了函数内部可以访问全局变量,而外部无法访问局部变量。
理解作用域:
var a = 10;
上方代码的赋值会执行两个操作,首先编译器会在当前作用域创建一个变量(若变量已经声明过,则会忽略该声明);然后运行时引擎会在作用域中查询该变量,如果能够找到就对其进行赋值。
LHS和RHS:
还是上方实例,引擎在查询时,会对变量进行LHS查询或者RHS查询。
- LHS:(赋值规则):变量出现在赋值操作符的左侧。如果当前作用域和上层作用域找不到该变量,则会悄悄地把它注册为全局变量。
- RHS:(访问规则):变量出现在赋值操作符的右侧。如果当前作用域和上层作用域找不到该变量,此时会报错。
LHS和RHS有什么用:
为什么区分LHS和RHS有很重要呢?
考虑一下代码:
function foo(a){
console.log(a+b);
b = a;
}
foo(2);
当执行函数第一条语句时,a和b显然时RHS,此时找不到b,因此是未定义;而当执行LHS查询时,找不到b,则会注册一个全局变量。
声明变量
-
var
:由var
声明的变量属于全局变量,在函数内声明则是局部变量。 -
let
,由let
声明的变量属于块级变量,即大括号。所以大括号之外的区域不可访问。 -
const
:由const
声明的变量也属于块级变量,且由它声明的变量会锁定,不可以进行重新赋值,但可以被更改。
变量提升:
由var
定义的全局变量会进行提升,移动到最前面。
console.log(a) //undefined
var a = 10;
上方代码执行结果为undefined
原因就是变量进行了提升,变成了这样:
var a;
console.log(a);
a = 10;
函数:
函数实际上是对象,每个函数都是Function实例,而函数名就是指向函数对象的指针。
函数定义:
- 函数声明:(最后没有分号)
function sayHello(){
let message = "hello!"
return message;
}
- 函数表达式:(最后有分号)
let sayHello = function(){
let message = "hello!"
return message;
};
- 构造函数:(不推荐)
let sayHello = new Function(){
let message = "hello!"
return message;
}
函数名:
函数名就是指向函数的指针,因此一个函数可以有多个名称。
function sum(num1,num2){
return num1+num2;
}
let sum1 = sum();
但下面的赋值代表着什么呢?
let sum2= sum;
是给将该函数赋值给了sum2吗?显然不是。上文已经提到,函数就是对象。
使用不带括号的函数名会访问函数指针,指向相同的函数,且不会执行该函数。
函数参数:
JavaScript参数有所不同,它不关心参数的多少、类型, 因为在函数内部,参数表现为一个数组。因此有了arguments
arguments
可以访问到传递给函数的所有参数,它是一个伪数组,例如:
function a(num) {
for (let i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
a(1, 2, 3, 4);
函数提升:
除了var
会提升之外,函数也会提升。并且同时存在变量提升和函数提升时,函数优先。
具名函数才会提升
fun(); //1
function fun() {
console.log(1);
}
foo(); //报错,TypeError
var foo = function bar() {
console.log(1);
};
上方代码分别使用函数声明和函数表达式进行定义函数,所得结果为什么不同呢?
因为函数表达式会当成变量提升,因此实际上是var foo
,因此会报错。由此可知,
函数声明会全部提升,函数表达式只会提升变量
var foo = function () {
console.log(1);
};
function foo() {
console.log(2);
}
foo(); //2
刚才已经提到函数表达式只会对变量提升,因此,上方代码就是定义foo
变量,并有两个相同函数名的函数,最后结果为2,可以知道JS中没有函数重载的概念,相同函数名会被覆盖
console.log(a); //函数
var a = 10;
function a() {
console.log("fun");
}
当函数和变量同名时,执行结果为函数,因此变量和函数同时存在时,函数优先并且同名会被覆盖。
立即调用函数(IIFE):
类似于函数声明,将函数包裹再括号中,模拟块级作用域。
(function () {
for (var i = 0; i < count; i++) {
console.log(i);
}
})();
更多内容请看:IFTS