ES5 基本语法变量篇的注意点
变量
变量概念
如果只是声明变量而没有赋值,则该变量的值是undefined。
var a;
console.log(a) // undefined
如果变量赋值的时候,忘了写var命令,这条语句也是有效的,但是这里创建的是全局变量。这种方式虽然可以,但是不利于理解和代码管理
function test () {
a = 1;
console.log(a) // 1
}
console.log(a) // 1
如果一个变量没有声明就直接使用,JavaScript 会报错,告诉你变量未定义。
console.log(x) // ReferenceError: x is not defined
可以在同一条var命令中声明多个变量;
var a, b;
console.log(a) // undefined
console.log(b) // undefined
var aa, bb = 10;
console.log(aa) // undefined
console.log(bb) // 10
(1)、如果使用var重新声明一个已经存在的变量,只是声明不赋值,第二次声明是无效的。
(2)、如果第二次声明赋值了,第二次覆盖第一次的。
(3)、注意这种情况限定在同一作用域中,作用域不同则不一样
var bb = 1;
var bb;
console.log(bb) // 1
var xx = 1;
var xx = 2;
console.log(xx) // 2
var x = 1; // 全局的
function test () {
var x = 2; // 局部
console.log('function_x--',x) // 2
}
test()
console.log('outter_x---',x) // 1
变量提升
JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升
console.log(a) // undefined
var a = 1;
// 真实的执行顺序
var a;
console.log(a)
a = 1;
补充!!!ES6之前,JavaScript没有块级作用域,只有全局作用域和函数作用域。变量提升就是将变量的声明提升到它所在的作用域的顶层
function test() {
var num = 123;
console.log(num); // 123
}
test();
console.log(num); // ReferenceError: num is not defined;num在函数作用域中
只有函数声明才存在函数提升
console.log(f1()); // f1f1
console.log(f2()); // undefined
function f1() {console.log('f1f1')} // 函数的声明
var f2 = function() {console.log('f2')} // 函数表达式
var str= "我是MT";
test();
function test() {
console.log(str); //undefined
var str= "哈哈哈";
console.log(str); //"哈哈哈"
}
console.log(str); //我是MT
函数外部的str是全局变量
函数内部的是str是局部变量,他们分属的作用域是不同的。
在函数内部,str的声明会被提升到函数的作用域的顶部。
function test(){
if("a" in window){
var a = 10;
}
console.log(a);
}
test(); // undefined
// 这里a会被提升到test的顶部执行,但是test是局部的,不会再window中,所以a被声明了但是没被赋值
var foo = 1;
function bar() {
if(!foo)
{
var foo = 10;
}
console.log(foo);
}
bar();// 10
//外面的foo和函数里面的foo不在同一个作用域中
var foo = 1;
function bar () {
var foo; // undefined
if (!foo) { // true
var foo = 10;
}
console.log(foo) // 10
}
bar()
function Foo() {
getName = function(){
console.log("1");
};
return this;
}
Foo.getName = function() {
console.log("2");
};
Foo.prototype.getName = function(){
console.log("3");
};
var getName = function() {
console.log("4");
};
function getName(){
console.log("5");
}
Foo.getName(); // 2
getName(); // 4
Foo().getName(); //1 ? 4 ? 2 ?报错
getName(); // ? 1
new Foo.getName(); // 2
new Foo().getName(); // 3
new new Foo().getName(); // 3
区块
对于var命令来说,JavaScript 的区块不构成单独的作用域
注意这里和ES6的区别
{
var a = 1;
}
console.log(a) // 1
switch结构
switch语句后面的表达式,与case语句后面的表示式比较运行结果时,采用的是严格相等运算符(=),而不是相等运算符(),这意味着比较时不会发生类型转换
var x = 1;
switch (x) {
case true:
console.log('x 发生类型转换');
break;
default:
console.log('x 没有发生类型转换');
}
// x 没有发生类型转换
三元运算符?:
(条件) ? 表达式1 : 表达式2
var n = 10;
var msg = '数字' + n + '是' + (n % 2 === 0 ? '偶数' : '奇数');
console.log(msg) // 数字10是偶数
标签(label)
JavaScript 语言允许,语句的前面有标签(label),相当于定位符,用于跳转到程序的任意位置,标签的格式如下。
标签通常与break语句和continue语句配合使用,跳出特定的循环
function t1() {
top:
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (i === 1 && j === 1) break top;
console.log('i=' + i + ', j=' + j);
}
}
console.log('bottom')
}
t1();
//i=0, j=0
//i=0, j=1
//i=0, j=2
//i=1, j=0
// 普通的break只能跳出内层循环,配合label后可以跳出外层循环