文章目录
1.变量提升
<script>
function sayHi() {
console.log(name);
console.log(age);
var name = '少年';
let age = 123;
}
sayHi();
</script>
代码运行如下:
解析:
undefind 和报错是因为 var 和let 声明的变量都具有变量提升的效果,
var 声明的变量并没有赋值,所以是 未定义的(undefind),
let 声明的变量不会初始化,不能在初始化完成时调用,这就是临时性死区的问题。
2.作用域
<script>
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1) //333
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1) //012
}
</script>
代码运行如下:
解析:
js的事件循环机制,setTimeout 属于宏任务(异步任务),要等同步任务执行完后才执行
var 在此处定义的是全局变量,同步任务执行完后的值 i 已经变成了3,所以 打印3个3
let 定义的变量会形成块级作用域,所以打印0 1 2
3.this指向
<script>
const shop = {
result: 12,
num1() {
return console.log(this.result * 2);
},
num2: () => {
return console.log(this.result * 2);
},
num3:function(){
return console.log(this.result * 2);
}
}
shop.num1(); //24
shop.num2(); //NaN
shop.num3();//24
</script>
代码运行如下:
解析:
num1 和 num3 输出的值为24,num2的值为NaN,因为js采用静态作用域,
函数的作用域在函数定义时就决定了
所以num1 和 num2 的中this的指向是shop,是定义时所在的对象,而不是使用时所在的对象
箭头函数不存在this
但是会捕获其所在的上下文的this的值,而shop对象是在全局中定义的,所以this指向window
4.符号
<script>
let a=+true;
let b= !'lisa';
let c= ! undefined;
let d =!null;
console.log(a);//1
console.log(b);//false
console.log(c);//true
console.log(d);//true
</script>
解析:
+ true 返回的是1 , + 更倾向返回一个值
!更倾向返回一个布尔值, !'lisa',返回的是false , 因为'lisa'是真实存在的,取反后返回的是false
对于undefined 和 null 来说,它们返回的值是false ,取反后为true
5.数据类型传参
5.1 简单数据类型传参
let c=123;
d=c;
d=456;
console.log(c);//123
console.log(d);//456
解析:
基本数据类型之间的复制
一个变量复制另外一个变量时,
相当于在栈中又开辟了一个空间,这个空间指向的位置是复制变量本身
复制变量的值改变了,并不会影响被复制的那个对象
5.2 引用数据类型传参
let a = {
age: 18
}
let b;
b = a;
b.age = 19;
console.log(a); //19
解析:
输出的结果为19
一个变量复制另一个变量的值时,如果被复制的对象是引用数据类型的情况下,
那么当变量复制下来后修改,自身的值时,被复制的那个对象的值也发生相应的改变.
在js中基本数据类型的值是放在栈当中,引用数据类型在栈中存放的是一个地址,地址的指向位置为堆
所以修改age这个值,就修改了age在堆中存的值,a 和 b 指向的是同一个地址,地址对应的值发生了变化 它们也发生了变化
6. “= =” 和 " = = ="
<script>
let a = 7;
let b = new Number(7);
let c = new Number(7);
let d = "7";
console.log(a == b); //true
console.log(a == d); //true
console.log(a === d); //false
console.log(c === b); //false
console.log(a === b); //false
</script>
解析:
== 指的是 数值相同 不考虑数据类型
=== 指的是 数值不仅要相等 数据类型也要相等
以上是针对基本数据类型来讲,在引用数据类型中又是不一样的
== 和 === 要求数值不仅要相等,同时他们指向的地址也要相等
这里的b和c虽然都是由Nember对象创建的,但他们指向的地址是不同的
b开辟的是一个地址,c开辟的又是一个新的地址
7.地址存放问题
<script>
let person = {
name: 'myname'
}
const your = [person];
person = null
console.log(your); //myname
</script>
解析:
这里很多小伙伴会问为什么打印的结果是myname,我已经将person改为了null
your中的person也应该变为null。其实这是因为person存放的这个对象的地址,
your的[0]存放的也是这个对象的地址,person只是将地址设置为null,并不会影
响到your[0]存放的地址。
8.值传递和引用传递
<script>
function info(str1, str2) {
str1.name = 'wu';
year = '2001';
}
let person = {
name: 'lisa'
};
let year = 2003;
info(person, year);
console.log(person, year);
</script>
解析:
函数传递参数的过程中时值传递还是引用传递,如果传递的是一个对象
时,就是引用传递,引用传递会影响到引用本身,但是值传递则不会
9.push返回值
<script>
function Info(item, arr) {
return arr.push(item)
}
let result = Info("apple", ['pear']);
console.log(result);
</script>
解析:
这里主要是考察push返回的是什么,普遍认为push返回的undefined,其实
返回的是添加后的数组长度