【JavaScript】Day3——函数、作用域、预解析

函数

声明函数 ↓

function getSum(num1, num2) {
    return num1 + num2;
}
// 如果没有返回值,则默认return undefined

形参与实参的匹配 ↓

// 下面的写法都是合法的哦 >_< 猜一下它们的返回值
getSum(1, 2);				
getSum(1, 2, 3);			
getSum(1);		

// 答案揭晓
// 返回3. 形参与实参的个数准确匹配
// 返回3. 多余的实参舍去,以形参可以接受的个数为准;需要注意这样并不会报错
// 返回NaN. 第二个形参没有实参给其传值,	好在它有默认值:undefined;计算后结果当然为NaN;值得注意的是这样也不会报错		

 
arguments的使用 ↓

当不确定有多少个实参需要传递时,可以用arguments来获取;

JS中,所有函数内置了一个arguments对象(直接用就行),arguments对象存储了传递的所有实参

arguments是一个伪数组

关于伪数组
首先它不是一个真正的数组,具有如下特征:
❶ 具有length属性
❷ 按索引的方式存储数据
❸ 不具有数组的push,pop等方法

 
arguments使用案例 ↓

// 求任意个数字的和
function getSum() {
    var sum = 0;
    for (var i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}

console.log(getSum(1));
console.log(getSum(1, 3, 8, 0, 9));

 
声明函数的第二种方式——匿名函数 ↓

var fun = function() {};
// fun是变量名,不是函数名;匿名函数没有函数名
// 可以这么理解,这个变量fun存的不是值,而是一个函数

// 既然是变量,它的初始化同样可以分两步写:
var fun;				// 声明
fun = function(){};		// 赋值

作用域
 
全局与局部

EC6之前,分为全局作用域局部作用域

变量也对应分为全局变量局部变量

需要注意的是,不声明直接赋值的变量也是全局变量:a = 233;

执行效率的角度来看,尽量少使用全局变量
 
块级作用域

目前可以认为JS没有块级作用域

这是个比较微妙的区别用Java和JS举个例子一看便知:

if(true) {
	int n = 233;
}
System.out.println(n);		// Java绝不会允许你这么做
if(true) {
	var n = 233;
}
console.log(n);				// 在JS中没有这么严格

※ 别把块级作用域函数体搞混了。函数体会出现局部变量,外部当让不能使用。
 
作用域链

其实我们在潜意识一直是遵守这个原则的,这里提一下作为依据

作用域链就是"一层一层向上找",就是"覆盖"

var n = 233
function func1() {
    var n = 65535
    function func2() {
        console.log(n)
    }
    func2();
}
func1();

// 输出65535.
// 可以理解为 n=65535 把 n=233 覆盖掉了
// 很简单的demo,但有助于我们理解作用域链是什么

 
预解析

先给几个坑,自行先体会:

console.log(a);				// 当然报错

console.log(n);				// 输出 undefined
var n = 233;				

func();
function func() {
    console.log('Loli Saikou!');		// 这当然是可以的
}									

fun();
var fun = function() {
    console.log('Loli Suki!');			// 这样会报错
}

☀ 下面揭晓答案

我们都知道JS代码是由浏览器的JS引擎执行的。JS引擎在运行JS代码时分两步:预解析代码执行
 
代码执行不必多说,脚本语言逐行执行

预解析就是把js代码里的所有var还有function提升到当前作用域的最前面。预解析是两方面的:

变量预解析变量提升):把所有的变量声明提升到当前作用域的最前面,不提升赋值操作

函数预解析函数提升):把所有的函数声明提升到当前作用域的最前面(函数的声明包括函数体

 
案例

// 结果是几?

var num = 10;
fun();
function fun() {
	console.log(num);
	var num = 20;
}

// 需要提升的东西有点多,因此先根据预解析的规则转化一下代码,再逐行执行
var num;
function fun() {
	var num;
	console.log(num);
	num = 20;
}
num = 10;
fun();
// 1.变量预解析,函数预解析
// 2.提升到当前作用域的最前面,注意函数内部也要预解析(作用域是这个函数体)
// 3.因为函数内部的声明将外部已被赋值的num覆盖掉了,因此答案是:undefined
// 陷阱题

function fun() {
    var a = b = c = 9;
    console.log(a);
    console.log(b);
    console.log(c);
}
fun();
console.log(c);
console.log(b);
console.log(a);

// 预解析不必多说,自己转化一下;真正的陷阱在于这两条语句的微妙区别:

var a = 9, b = 9, c = 9;	// 声明并复制了三个变量
var a = b = c = 9;			// 声明了a,然后给a,b,c赋值(并没有声明b,c)
// 后者等价于 var a = 9; b = 9; c = 9; b和c变成了全局变量

// 答案为:9 9 9  9 9 报错

 
☀ Loli & JS

♫ Saikou

猜你喜欢

转载自blog.csdn.net/m0_46202073/article/details/106428161