Javascript 变量
变量提升
只有var声明的变量存在变量提升!!!!
let和const都没有变量提升!!
变量提升提升的是定义而不是赋值!!
所谓定义,就是变量声明的过程,此时的变量是没有被赋值的。
console.log(a);//undefine
var a=80;
上面的代码等价于
var a;//变量提升的实质就是把变量的声明提到顶部
console.log(a);//undefine
a=50
let 和 const无变量提升
console.log(x,y);//ReferenceError x,y is not defined
let x = 100;
const y =80;
let 和 var 与 const
let和var还有const都存在变量提升
var用于定义全局变量,而且用var定义的全局变量,不能再用let 或者 const 标识符再次定义,而可以用var标识符在定义,达到覆盖的效果。而let和const不行。
var a = 'aaaa';
var a = 'bbbb';//OK
let str = 'hello world';
let str = 'Bye';//不ok str has been declared
let的暂时性死区问题
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
var str='nihao';
function fn(){
str='baibai';
}
fn();//是可以改变str的值的
var str='nihao';
function fn(){
let str;//let str只适用于这个函数里面
str='baibai';
console.log(str); //baibai
}
fn();//无法改变str的值的
console.log(str);//nihao
变量赋值
解构赋值
所谓解构赋值,就是从数组中提取参数为变量进行赋值的一种方法。
解构赋值等号左边是右边的模板,可以使用剩余参数。
完全解构(对称解构)
let [a,b,c]=[1,2,3];
解构数组
var foo = ["一", "二", "三"];
var [one, two, three] = foo;
console.log(one); // "一"
console.log(two); // "二"
console.log(three); // "三"
不完全解构(非对称解构)
let [a,b,c]=[1,2];
//c = undefine
let [a,b,c]=[1,2,3,4];
//c = undefine
使用剩余参数
let [a,b,c,...e]=[1,2,3,4,5,8,9,7,6,49];
//e: Array(7)=[4,5,8,9,7,6,49]
使用空占位
let [ , , , , ,...e]=[1,2,3,4,5,8,9,7,6,49];//空格不是必须的,这里输入空格只是为了看的清晰
//前面5个数字被占了
//e: Array(5)=[8,9,7,6,49]
交换数字
let a=30;
let b=60;
[a,b] = [b,c];
//a=60;
//b=30;
解构对象
({ a, b } = { a: 10, b: 20 });
//js 不允许语句以花括号开头,所以要用括号包裹住解构对象语句
console.log(a); // 10
console.log(b); // 20
解构对象时使用剩余参数
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); // {c: 30, d: 40}
可以用返回值时数组的函数进行解析
function f() {
return [1, 2];
}
var a, b;
[a, b] = f();
console.log(a); // 1
console.log(b); // 2
传值赋值与引用赋值
传值赋值
js中一些基础变量,如Number,String,Boolean的传值方式是值传递,也就是浅拷贝,是数值之间的传递。
var a = 50;
var b = a;
console.log(a);//50
console.log(b);//50
a = 100;
console.log(a);//100
console.log(b);//50
传值复制:b并不会因为a的改变而改变。
引用赋值
js中的对象,如Array、Object的传递方式是引用传递,也就是深拷贝,是地址与地址的传递
var obj = {
a : 1,
b : 2
}
var obj1 = {
a : 11,
b : 22
}
obj = obj1;
obj1.a =999;
console.log(obj); //=>{a:11,b:999}
obj与obj1在内存中的存储是这样的:
栈内存:
Name | address |
---|---|
obj | 0x100 |
obj1 | 0x101 |
堆内存:
address | value |
---|---|
0x100 | {a:1,b:2} |
0x101 | {a:11,b:22} |
执行语句obj = obj1;
之后会变成这样:
Name | address |
---|---|
obj | 0x101 |
obj1 | 0x101 |
执行语句obj1.a =999;
之后,
address | value |
---|---|
0x100 | {a:1,b:2} |
0x101 | {a:11,b:999} |
引用复制:obj会因为obj1的改变而改变。
模板字符串
模板字符串是允许嵌入表达式的字符串字面量。模板字符串使用反引号 (` `) 来代替普通字符串中的用双引号和单引号。模板字符串可以包含特定语法${expression}
的占位符。
let name = "John";
// let aq = "hello ${name}"; 语法错误 输出还是hello ${name} 模板字符串应该用“反引号(`)来包围”
let aq = `hello ${name}`; //语法正确 ${}模板字面量 用于解释变量
//aq中,字面量是hello 插值是${name}
console.log(aq); //hello John
let arr = ['1', '2', '3'];
let cd = `
<a>${arr[0]}</a>
`;
console.log(cd); // <a>1</a>
关于模板字符串的详细内容请看:https://blog.csdn.net/weixin_46229315/article/details/123743354
赋值的注意事项
使用连续赋值的时候,可能不一定是你想要的效果:
const a=b=50;
/*想象中的
const a=50;
const b=50;
*/
/*实际上的
const a=b;
const b=50;
*/
这样会导致什么问题呢?
由于a与b是传值赋值。所以当使用const a=b=50;
来赋值时,然后更改b的值,这时,a的值并不会因为b的变化而变化。