JavaScript 高级程序设计(第四版)
三、语言基础
(一)语法
1.区分大小写
变量test和Test不同
2.标识符
(1)第一个字符必须为字母、下划线(_)或$,剩下的可以是字母、下划线、美元符号或数字,按照惯例,标识符使用驼峰写法(menuList)。
(2)标识符不能为关键字: a ECMA-262第6版规定的所有关键字 b ECMA-262第6版为将来保留的所有词汇
始终保留
严格模式下保留
模块代码中保留
3.严格模式
一种不同于JavaScript解析和执行模型,处理es3中不规范写法,对不安全活动抛出错误
'use strict'
(1)脚本开头
(2)函数内部
function () {
'use strict'
}
4.语句
(1)最好在语句最后使用分号
(2)类似
if (test) {
console.log(test)
};
不要省略为
if (test) console.log(test);
5.变量
var 定义变量关键字
var 声明的变量可以再次改变变量值类型,但是不推荐
text1 var声明的变量具有函数作用域,该变量在函数退出时销毁
text2 函数作用域内变量未声明直接赋值会成为全局变量。不推荐,严格模式下会报错
text3 声明提升:var声明的变量会将变量声明提升到函数作用域顶部
text4 可反复声明,值为最后一个
console.log(text3); //undefined
function test() {
var text1 = 'wen'
text2 = 123
}
test()
var text3 = '123'
console.log(text1); //Uncaught ReferenceError: text is not defined
console.log(text2); //123
var text4 = 1
var text4 = 2
var text4 = 3
let const
let const声明的为块级作用域 代码块{} 嵌套使用相同标识符不会出错
let num1 = 1
console.log(num1); // 1
if (!num1) {
let num1 = 2
console.log(num1); // 2
}
不可重复声明 var 和 let或const 声明同一个变量也会报错
没有变量提升,在let声明之前的执行瞬间称为‘暂时性死区’
const 声明的变量称为常量,必须拥有初始值。 且不能改变引用,即声明位于栈的简单数据类型不能改变值,声明位于堆的对象不能改变引用地址,但可以改变内部属性值
不能用const声明会自增的迭代变量,因为改变了值,违反const规则
for 循环中的var 和 let
var
1.var 声明的i 作用域为全局,所以for循环外也可以打印
for (var i = 0; i < 5; ++i) {}
console.log(i); // 5
let 声明的i 作用域为块级,所以for循环外获取不到i,报错
for (let i = 0; i < 5; ++i) {}
console.log(i); // Uncaught ReferenceError: i is not defined
var 每次for循环迭代变量为同一变量因此打印的为最终退出循环的变量 5
for (var i = 0; i < 5; ++i) {
setTimeout(() => {
console.log(i) // 5 5 5 5 5
}, 0);
}
事件执行顺序
首先执行第一次for 循环 var i = 0 然后遇到异步任务 setTimeout 放到任务队列
第二次 var i = 1 遇到setTimeout 放到任务队列
第三次 var i = 2 遇到setTimeout 放到任务队列
第四次 var i = 3 遇到setTimeout 放到任务队列
第五次 var i = 4 遇到setTimeout 放到任务队列
第六次 i = 5 不满足条件,跳出循环,此时 var i = 5
此时再从任务队列中取出setTimeout 打印,均会打印出5,
所以最终结果为:5 5 5 5 5
let 每次for循环迭代变量为不同代码块变量
for (let i = 0; i < 5; ++i) {
setTimeout(() => {
console.log(i) // 0 1 2 3 4
}, 0);
}
事件执行顺序
首先执行第一次for 循环 let i = 0 然后遇到异步任务 setTimeout 放到任务队列
第二次 let i = 1 遇到setTimeout 放到任务队列
第三次 let i = 2 遇到setTimeout 放到任务队列
第四次 let i = 3 遇到setTimeout 放到任务队列
第五次 let i = 4 遇到setTimeout 放到任务队列
第六次 i = 5 不满足条件,跳出循环,let i = 5
此时再从任务队列中取出setTimeout 打印,由于每次打印时let声明的i为块级作用域,所以setTimeout打印的为该作用域内的i
所以最终打印结果为:0 1 2 3 4
声明风格最佳实践
const > let > var(尽量不使用)
6.数据类型
(1) typeof 用来检测任意变量的数据类型
let text1;
let s = Symbol('foo')
function test() {}
console.log(typeof 1); //number
console.log(typeof '1'); //string
console.log(typeof true); //boolean
console.log(typeof undefined); //undefined
console.log(typeof text2); //undefined
console.log(typeof text); //undefined
console.log(typeof null); //object
console.log(typeof test); //function
console.log(typeof s); //symbol
(2) Undefined 假值,理论上来说无法进行实际操作
声明变量但未赋值,值初始化为undefined,一个未声明的变量通过typeof检测都是undefined,但其实不一样
(3)Null 空对象指针,在初始化将来要保存对象的变量时,赋值为null
console(undefined == null) //true ==操作符会转换操作数
(4)Boolean
true:
非空字符串、非零数值(包括无穷值)、任意对象、N/A
false:
''、0,NaN、null、undefined
(5)Number
浮点值
包含小数点且小数点后至少有一个数字
存储浮点值是整值的两倍,所以ECMAScript总会把1.当初1处理,10.0当成10处理
科学计数法
数值后跟一个大写或小写e,e后面跟10的几次方
1.1e3 等于 1100
3.125e7 等于 31250000
3e-7 等于 0.0000003
值的范围
最小值:Number.MAX_VALUE
最大值:Number.MIN_VALUE
如果超出该范围 表示为Infinity或-Infinity
isFinite()用来确定值是不是有限大
const res = Number.MAX_VALUE + Number.MAX_VALUE
console.log(isFinite(res)); //false
console.log(Number.NEGATIVE_INFINITY); // -Infinity
console.log(Number.POSITIVE_INFINITY); // Infinity
NaN
不是数值,用于本来要返回数值的操作结果失败了,不是抛出错误
console.log(0 / 0); //NaN
console.log(-0 / +0); //NaN
console.log(5 / 0); //Infinity
console.log(5 / -0); //-Infinity
// 任何涉及NaN的操作数都返回NaN
// NaN不等于任何值,包括自身
console.log(NaN == NaN); //false
// isNaN判断传入的参数是否是非数值,可以判断对象
console.log(isNaN(NaN)); //true
console.log(isNaN(false)); //false 布尔值可以转换为1、0
数值转换
Number()
转型数据,可以用于任何数据类型 布尔值:true 1;false 0 数值:直接返回 null:0 undefined:NaN 字符串: 如果字符串是有效的数值或者十六进制数,10进制直接转换为对应的数值,忽略前面的0,十六进制转换为10进制 空字符串:0 其他情况:NaN
parseInt()
用来转换整数值 字符串第一值如果不是数值、加减号,立即返回NaN,因此空字符串为NaN
console.log(parseInt('P1')); //NaN
console.log(parseInt('1P')); //1
console.log(parseInt('11.2POI')); //11
console.log(parseInt('')); //NaN
接受第二个参数用来解析不同进制数
console.log(parseInt('0xAF', 16)); //175
console.log(parseInt('AF', 16)); //175 可以省略0x,在传入第二个参数后
console.log(parseInt('AF')); //NaN
console.log(parseInt('12', 2)); //1
console.log(parseInt('12', 8)); //10
console.log(parseInt('12', 10)); //12
console.log(parseInt('12', 16)); //18
parseFloat()
和parseInt规则一致,但有两个地方不同 可以转换第一个小数点;没有第二个参数,始终解析十进制数
console.log(parseFloat('0xAF')); //0
console.log(parseFloat('010.1.1')); //10.1
console.log(parseFloat('1.2e5')); //12000