提升(Hoisting)是 JavaScript 将声明移至顶部的默认行为。
1.JavaScript 声明会被提升
在 JavaScript 中,可以在使用var
定义变量之后对其进行声明。
换句话说,可以在声明变量之前使用它。
x = 5; // 把 5 赋值给 x
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x; // 在元素中显示 x
var x; // 声明 x
2.let 和 const 关键字
用 let
或 const
声明的变量和常量不会被提升!
在声明 let
或 const
变量之前就使用它会导致 ReferenceError。
JavaScript 块作用域
通过 var
关键词声明的变量没有块作用域。
在块 {}
内声明的变量可以从块之外进行访问。
{
var x = 10;
}
// 此处可以使用 x
可以使用 let
关键词声明拥有块作用域的变量。
在块 {}
内声明的变量无法从块外访问:
{
let x = 10;
}
// 此处不可以使用 x
重新声明变量
使用 var
关键字重新声明变量会带来问题。
在块中重新声明变量也将重新声明块外的变量:
var x = 10;
// 此处 x 为 10
{
var x = 6;
// 此处 x 为 6
}
// 此处 x 为 6
使用 let
关键字重新声明变量可以解决这个问题。
在块中重新声明变量不会重新声明块外的变量:
var x = 10;
// 此处 x 为 10
{
let x = 6;
// 此处 x 为 6
}
// 此处 x 为 10
允许在程序的任何位置使用 var
重新声明 JavaScript 变量。
在相同的作用域,或在相同的块中,通过 let
重新声明一个 var
变量是不允许的。
在相同的作用域,或在相同的块中,通过 let
重新声明一个 let
变量是不允许的。
在不同的作用域或块中,通过 let
重新声明变量是允许的。
循环作用域
在循环中使用 var
:
var i = 7;
for (var i = 0; i < 10; i++) {
// 一些语句
}
// 此处,i 为 10
在循环中使用 let
:
let i = 7;
for (let i = 0; i < 10; i++) {
// 一些语句
}
// 此处 i 为 7
如果在循环中用 let
声明了变量 i
,那么只有在循环内,变量 i
才是可见的。
函数作用域
在函数内声明变量时,使用 var
和 let
很相似。
它们都有函数作用域:
function myFunction() {
var carName = “porsche”; // 函数作用域
}
function myFunction() {
let carName = “porsche”; // 函数作用域
}
全局作用域
如果在块外声明声明,那么 var
和 let
也很相似。
它们都拥有全局作用域:
var x = 10; // 全局作用域
let y = 6; // 全局作用域
HTML 中的全局变量
通过 var
关键词定义的全局变量属于 window
对象。
通过 let
关键词定义的全局变量不属于 window
对象。
通过 const 定义的变量与 let 变量类似,但不能重新赋值。
const 变量必须在声明时赋值。
不正确:
const PI;
PI = 3.14159265359;
正确:
const PI = 3.14159265359;
关键字 const
有一定的误导性。
它没有定义常量值。它定义了对值的常量引用。
因此,我们不能更改常量原始值,但我们可以更改常量对象的属性。
常量对象:可以更改属性,不能为对象赋值。
const car = {type:“porsche”, model:“911”, color:“Black”};
car.color = “White”;// 可以更改属性
car.owner = “Bill”;// 可以添加属性
car = {type:“Volvo”, model:“XC60”, color:“White”}; // ERROR
常量数组:可以更改数组元素,不能为数组赋值。
const cars = [“Audi”, “BMW”, “porsche”];
cars[0] = “Honda”;// 可以更改元素
cars.push(“Volvo”);// 可以添加元素
cars = [“Honda”, “Toyota”, “Volvo”]; // ERROR
重新声明
在程序中的任何位置都允许重新声明 JavaScript var
变量。
在同一作用域或块中,不允许将已有的 var
或 let
变量重新声明或重新赋值给 const
。
在同一作用域或块中,为已有的 const
变量重新声明声明或赋值是不允许的。
在另外的作用域或块中重新声明 const
是允许的。
3.JavaScript 初始化不会被提升
JavaScript 只提升声明,而非初始化。
点击此处,查看例子
严格模式请查看W3C的指南
请避免全局变量、new
、===
、eval()
1.避免全局变量
请尽量少地使用全局变量。
它包括所有的数据类型、对象和函数。
全局变量和函数可被其他脚本覆盖。
请使用局部变量替代,并学习如何使用闭包。
2.始终声明局部变量
所有在函数中使用的变量应该被声明为局部变量。
局部变量必须通过 var 关键词来声明,否则它们将变成全局变量。
严格模式不允许未声明的变量。
3.在顶部声明、初始化变量
4.请不要声明数值、字符串或布尔对象
避免使用new Number()/String()/Boolean()
5.请勿使用 new Object()
请使用 {}
来代替 new Object()
请使用""
来代替new String()
请使用0
来代替 new Number()
请使用 false
来代替 new Boolean()
请使用[]
来代替new Array()
请使用 /()/
来代替 new RegExp()
请使用function (){}
来代替 new Function()
6.意识到自动类型转换
请意识到数值会被意外转换为字符串或 NaN
(Not a Number)。
JavaScript 属于松散类型。变量可包含不同的数据类型,并且变量能够改变其数据类型。
如果进行数学运算,JavaScript 能够将数值转换为字符串。
用字符串减去字符串,不会产生错误而是返回 NaN
(Not a Number。
7.使用 === 比较
==
比较运算符总是在比较之前进行类型转换(以匹配类型)。
===
运算符会强制对值和类型进行比较。
Undefined 不是 Null
JavaScript 对象、变量、属性和方法可以是未定义的。
此外,空的 JavaScript 对象的值可以为 null
。
这可能会使测试对象是否为空变得有点困难。
可以通过测试类型是否为 undefined
,来测试对象是否存在:
if (typeof myObj === "undefined")
但是您无法测试对象是否为 null,因为如果对象未定义,将抛出错误:
if (myObj === null) //若myObj未定义,则有错误抛出
在测试非 null 之前,必须先测试未定义:
if (typeof myObj !== "undefined" && myObj !== null)
8.为函数设置默认参数
如果调用函数时缺少一个参数,那么这个缺失参数的值会被设置为 undefined
。
9.用 default 来结束 switch
请使用使用 default 来结束您的 switch 语句。
10.避免使用 eval()
eval() 函数用于将文本作为代码来允许。
ECMAScript 5 - JavaScript 5
ECMAScript 5 也称为 ES5 和 ECMAScript 2009。
ECMAScript 5 特性
这些是 2009 年发布的新特性:
●"use strict" 指令
:“严格模式”
●String.trim()
: 删除字符串两端的空白字符。
●Array.isArray()
:方法检查对象是否为数组。
●Array.forEach()
:为每个数组元素调用一次函数。
●Array.map()
:对每个数组元素执行函数来创建新数组
●Array.filter()
:创建一个包含通过测试的数组元素的新数组。
●Array.reduce()
:在每个数组元素上运行函数,以生成(减少它)单个值。从左到右。
●Array.reduceRight()
:在每个数组元素上运行函数,以生成(减少它)单个值。从右到左。
●Array.every()
:检查所有数组值是否通过测试。返回布尔值。
●Array.some()
:检查某些数组值是否通过了测试。返回布尔值。
●Array.indexOf()
:在数组中搜索元素值并返回其位置。
●Array.lastIndexOf()
:在数组中搜索元素值并返回其位置。从结尾开始。
●JSON.parse()
: 用于将文本转换为 JavaScript 对象。
●JSON.stringify()
: 将JS对象转换为JSON字符串
●Date.now()
:返回自零日期(1970 年 1 月 1 日 00:00:00:00)以来的毫秒数。
●属性 Getter 和 Setter
:get、set对象访问器。
●新的对象属性和方法
:很多,点击查看JS对象ES5新方法。
以上来自W3C的ES5,此篇都是学习笔记。
ECMAScript 6 - ECMAScript 2015
ECMAScript 6 也称为 ES6 和 ECMAScript 2015。
一些人把它称作 JavaScript 6。
1.本章介绍 ES6 中的一些新特性。
●JavaScript let
:允许使用块作用域声明变量。
●JavaScript const
:允许声明常量(具有常量值的 JavaScript 变量)。
●幂 (**)
:x ** y 的结果与 Math.pow(x,y) 相同。
●默认参数值
:函数参数具有默认值。
●Array.find()
:返回通过测试函数的第一个数组元素的值。
●Array.findIndex()
:返回通过测试函数的第一个数组元素的索引。
2.新的数字属性
ES6 将以下属性添加到 Number 对象:
●EPSILON
●MIN_SAFE_INTEGER
●MAX_SAFE_INTEGER
3.新的数字方法
ES6 为 Number 对象添加了 2 个新方法:
●Number.isInteger()
如果参数是整数,则 Number.isInteger()
方法返回 true
。
●Number.isSafeInteger()
安全整数是可以精确表示为双精度数的整数。
如果参数是安全整数,则 Number.isSafeInteger()
方法返回 true
。
安全整数指的是从 -(253 - 1) 到 +(253 - 1) 的所有整数。
4.新的全局方法
ES6 还增加了 2 个新的全局数字方法:
●isFinite()
如果参数为 Infinity
或 NaN
,则全局 isFinite()
方法返回 false
。
否则返回 true
。
●isNaN()
如果参数是 NaN
,则全局 isNaN()
方法返回 true
。否则返回 false
。
5.箭头函数(Arrow Function)
箭头函数允许使用简短的语法来编写函数表达式。
不需要 function 关键字、return 关键字以及花括号。
箭头功能没有自己的 this
。它们不适合定义对象方法。
箭头功能未被提升。它们必须在使用前进行定义。
使用 const
比使用 var
更安全,因为函数表达式始终是常量值。
如果函数是单个语句,则只能省略 return 关键字和花括号。因此,保留它们可能是一个好习惯:
const x = (x, y) => { return x * y };