复盘JS
var
var是js的一个关键字,它是用来声明变量的。
使用var声明一个变量有两种方式:
第一种:var num=1。如果在方法中声明,则为局部变量;如果在全局中声明,则为全局变量,等价于 window.var num = 1
第二种:num=1。事实上这是对属性进行赋值操作。首先,它会尝试在当前作用域链(如果在方法中声明,则当前作用域代表全局作用域和方法局部作用域)中解析num,如果在任何当前作用域链中找到num,则会对num属性进行赋值,如果没有找到num,他会在全局对象(即当前作用域链的最顶层对象,如window对象)中创造num属性并赋值
注意!它并不是声明了一个全局变量,而是创建了一个全局对象的属性
由于变量声明自带不可删除属性,比较var num=1跟num=1,前者是变量声明,带不可删除属性,因此无法被删除;后者为全局变量的一个属性,因此可以从全局变量中删除。
使用var声明变量会发生变量提升,因为JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行的运行,这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升.
// 变量声明提升(实际上只是声明变量那一步提升了,赋值并没有)
//例1
console.log(num); // undefined
var num = 1
//并不会报错 实际上解析后的代码为
var num; // 先声明的变量并没有赋值
console.log(num) // 输出的为未定义
num = 1
// 经典面试题
console.log(v1); // undefined
var v1 = 100;
function foo() {
console.log(v1); //undefined
var v1 = 200;
console.log(v1); //200
}
foo();
console.log(v1); //100
// 提升后
var v1;
console.log(v1);
function foo() {
var v1;
console.log(v1);
v1 = 200
console.log(v1)
}
v1 = 100
foo();
console.log(v1)
// javascript中不仅仅是变量声明有提升的现象,函数的声明也是一样;具名函数的声明有两种方式:
//函数声明式
function bar () {}
//函数字面量式
var foo = function () {}
// 函数字面量提升与声明变量提升相同,即:
var foo;
foo = function (){}
// 函数声明式按照上下文格式自动提升的顶端,例:
foo(); //1
var foo;
function foo () {
console.log(1);
}
foo = function () {
console.log(2);
}
// 提升后
function foo() {console.log(1)}
foo();
var foo;
foo = function () {
console.log(2);
}
let 和 const
ES2015(ES6) 新增加了两个重要的 JavaScript 关键字: let 和 const。let 声明的变量只在 let 命令所在的代码块内有效。const 声明一个只读的常量,一旦声明,常量的值就不能改变。在 ES6 之前,JavaScript 只有两种作用域: 全局变量 与 函数内的局部变量。
let
//讲到这个let,就不得不说一下JavaScript 块级作用域(Block Scope)也可以理解为局部作用域,函数体内也是局部作用域
// 注:使用 var 关键字声明的变量不具备块级作用域的特性,它在 {} 外依然能被访问到。
{
var a = 1
}
console.log(a) // 1 在块级作用域外也能访问到a变量
//在 ES6 之前,是没有块级作用域的概念的。ES6 可以使用 let 关键字来实现块级作用域。let 声明的变量只在 let 命令所在的代码块 {} 内有效,在 {} 之外不能访问。
{
let b = 2
}
console.log(b) //undefined 作用域外无法访问到let声明的变量
// 注 : 在同一作用域中不能使用let或var重置let声明的变量,var也不能重置let声明的变量,且let不会发生变量提升
const
>const 用于声明一个或多个常量,声明时必须进行初始化,且初始化后值不可再修改
const PI = 3.141592653589793;
PI = 3.14; // 报错
PI = PI + 10; // 报错
const str; // 报错
const
定义常量与使用let
定义的变量相似:
- 二者都是块级作用域
- 都不能和它所在作用域内的其他变量或函数拥有相同的名称
两者还有以下两点区别:
const
声明的常量必须初始化,而let
声明的变量不用- const 定义常量的值不能通过再赋值修改,也不能再次声明。而 let 定义的变量值可以修改。
const并非真正的常量
const 的本质: const 定义的变量并非常量,并非不可变,它定义了一个常量引用一个值。使用 const 定义的对象或者数组,其实是可变的。下面的代码并不会报错:
// 创建常量对象
const car = {type:"Fiat", model:"500", color:"white"};
// 修改属性:
car.color = "red";
// 添加属性
car.owner = "Johnson";
//但是我们不能对常量对象重新赋值:
const car = {type:"Fiat", model:"500", color:"white"};
car = {type:"Volvo", model:"EX60", color:"red"}; // 错误
//以下实例修改常量数组:
// 创建常量数组
const cars = ["Saab", "Volvo", "BMW"];
// 修改元素
cars[0] = "Toyota";
// 添加元素
cars.push("Audi");
//数组也不能赋值
const cars = ["Saab", "Volvo", "BMW"];
cars = ["Toyota", "Volvo", "Audi"]; // 错误
各位同道需要及时整理所学