赞
踩
区分大小写
标识符:变量、函数、属性或函数参数的名称
1.第一个字符必须是字母,下划线(_)或美元符号($)
2.剩下的其他字符可以是字母、下划线、美元符号或者数字
关键字、保留字、true、false和null不能作为标识符
注释:单行注释(//),多行注释(/**/)
严格模式:一些不规范的写法会在这种模式下被处理,在脚本开头加上
"use strict"
语句:分号结尾,虽然不是必须的,加分号有利于删除空行压缩代码
多条语句用花括号({})包围,即使是一条语句也建议用花括号包着
最好不要使用关键字和保留字作为标识符和属性名
变量可以保存任何类型的数据,每个变量不过只是一个用于保存任意值的命名占位符。有三个关键字可以声明变量:var,const,和let
1.3.1 var
var message;
这行代码定义了一个名为message的变量,可以保存任何类型的值。如果不初始化变量会保存一个特殊值undefined
var message = "hi";
这里,message被定义为一个保存字符串hi的变量,这样初始化并不会把它识别为字符串类型,只是一个简单的赋值
var mesage = "hi";
message = 10;//不推荐这样写
1.var的声明作用域
使用var操作符定义的变量会成为包含它的函数的局部变量。
function test(){ var message = "hi"; } test(); console.log(message);//出错!
原因是message是在函数内部用var定义的,函数名叫做test(),调用它并给message赋值。调用完成变量就会被销毁,所以会导致最后一行报错。
但是如果在函数内定义变量时省略var操作符,就可以创建一个全局变量:
function test(){ message = "hi";//全局变量 } test(); console.log(message);//hi
并不推荐省略var定义全局变量,严格模式下则会抛出异常
如果需要定义多个变量,可以在一条语句中用逗号分隔每个变量
var message = "hi" found = false; age = 29;
这里定义并初始化了三个变量。
2.var声明提升
使用var时,使用以下代码不会报错,原因是var会自动提升到函数作用域顶部
function foo(){ console.log(age); var age = 26; } foo(); //underfined
不会报错是因为,它等价于以下代码
function foo(){ var age; console.log(age); age = 26; } foo(); //underfined
反复使用var声明同一个变量也可以
function foo(){ var age = 16; var age = 26; var age = 36; console.log(age); } foo(); //36
1.3.2 let
和var作用差不多,最明显的区别是,let声明的范围是块作用域,而var声明的范围是函数作用域。
if(true) { var name = 'Matt'; console.log(name); //Matt } console.log(name); //Matt if (true) { let age = 26; console.log(age); //26 } console.log(age); //ReferenceError:age 没有定义
此时age之所以不能在if外被引用,是因为let的作用域仅限于该块内部
let 也不允许同一个块作用域中出现冗余声明,这样会导致报错:
var name; var name; let age; let age; //SyntaxError;标识符age已经声明过了
由于JavaScrip会记录比用于变量声明的标识符以及所在的块作用域,因此嵌套使用相同的标识符不会报错,这是因为同一个块中没有重复声明:
var name = "Mick"; console.log(name); //Mick if(true) { var name = "Matt"; console.name(name) //Matt } let age = 30; console.log(age); //30 if (true) { let age = 26; console.log(age);//26 }
var和let不能同时声明一个相同的变量
var name;
let name; //SyntaxError
1.暂时性死区
var和let的另外一个重要的区别,就是let声明的变量不会在作用域中被提升。
// name 会被提升 console.log(name); //undefined var name = 'Matt'; //age 不会被提升 console.log(age); // ReferenceError:age 没有定义 let age = 26;
在let声明之前的执行瞬间被称为"暂时性死区",在此阶段引用任何后面才声明的变量就会抛出ReferenceError。
2.全局声明
使用let在全局作用域中声明的变量不会成为window对象的属性(var 声明的变量则会)
var name = 'Matt'; console.log(window.name); //'Matt' let age = 26; console.log(window.age); //undefined
不过let声明仍然在全局作用域中发生,为了避免SyntaxError,必须确保页面不会重复生命同一个变量。
3.条件声明
由于在使用var声明变量的时候,由于声明的会提升,所以JS的引擎会自动将多余的声明在作用域顶部合为一个声明。
由于let的作用域是块,所以不可能检查前面是否使用let声明过同名变量,同时也就不能在没有声明的情况下声明它。
<script> var name = 'Matt'; let age = 26; </script> <script> //假设脚本不确定页面中是否以及声明了同名变量 //那它可以假设还没有声明过 var name = 'Nicholas'; //这里没问题,因为可以被作为一个提升声明来处理 //这里不需要检查之前是否声明过同名变量 let age = 36; //如果age之前声明过,这里会报错 </script>
let也不能依赖条件声明模式。
4.for循环中的let声明
for循环定义的迭代变量会渗透到循环体外部、
for (var i = 0; i<5; ++i){ //循环逻辑 } console.log(i); //5
改使用let之后,迭代变量的作用域仅限于for循环内部
for(let i = 0 ; i<5; ++i) { //循环逻辑 } console.log(i); //ReferenceError:i没有定义
在使用var的时候,最常见的问题就是对迭代遍历的奇特声明和修改:
for(var i = 0; i<5; ++i){ setTimeout(()=>console.log(i),0); } //会输出5,5,5,5,5
之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。此时所有的i都是同一个变量。
for(let i = 0; i<5; ++i){ setTimeout(()=>console.log(i),0); } //会输出0,1,2,3,4
在使用let声明迭代变量的时候,JS会在后台为每一个迭代循环声明一个新的迭代变量。每一次循环引用的都是不一样的变量实例。
这种每次迭代声明一个独立变量实例的行为适用于所有风格的for循环。
1.3.3 const
行为于let基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改const声明的变量会导致运行时出错。
const age = 26; age = 36; //TypeError:给常量赋值 //const也不允许重复声明 const name = 'Matt'; const name = 'Nicholas';// SyntaxError //const声明的作用域也是块 const name = 'Matt'; if(true) { const name = 'abc'; } console.log(name); //Matt;
const声明的限制值适用于它指向的变量的引用,所以如果const引用的是一个对象,那么修改这个对象内部的属性并不违反const的限制。
const.person={}; person.name = 'Matt';// ok
不能使用const来迭代变量。
1.3.4 声明风格及最佳实践
不使用var
const优先,let次之
Undefined、Null、Boolean、Number、 String 和 Symbol。Symbol(符号)是 ECMAScript 6 新增的。还有一种复杂数据类型叫 Object(对 象)。Object 是一种无序名值对的集合。因为在 ECMAScript 中不能定义自己的数据类型,所有值都可 以用上述 7 种数据类型之一来表示。
1.4.1 typeof 操作符
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。