语法
以下是js的语法要求
- 大小写敏感
- 标识符: 即我们说的变量名 开头必须是字幕/下划线/&的一种
- 不能把关键字/保留字/true,false,null作为标识符
- 注释:
- 单行注销: //
- 多行注销: / here is your code /
- 严格模式: Es5引入严格模式,在严格模式下,ECMAScript 3 中的一些不确定的行为将得到处理,而且对某些不安全的操作也会抛出错误。用法
- 在顶部添加
"use strict"; - 在函数内部第一行添加
- 在顶部添加
- 语句: 建议每一行语句背后加分号, 哪怕这不是必须的-因为解释器会自行补充 , 不过这样会耗费时间和性能.
关键字和保留字
Reserved Words - JavaScript | MDN 可以查看最新的关键字和保留字
以上都是不能作为标识符的.
变量
使用var/let/const都可以声明一个变量
- var: 有声明提升,可重复声明
- let:和var类似,但是:
- 具备块作用域,如:{ }
- 不可重复声明
- 在全局作用域中不可读取let声明的变量
- for循环中的let ,和for循环中的var表现不一致。主要原因是 JavaScript 引擎在后台会为每个迭代循环声明一个新的迭代变量。 每个 setTimeout 引用的都是不同的变量实例
- const:与let基本类似,用于声明常量,修改const声明会报错
声明风格和最佳实践:
- 不使用var
- 优先使用const,再let。因为使用const声明的时候,将来有人覆盖某一个变量,可迅速查出
数据类型
原始类型:
- Undefined
- Null
- Boolean
- Number
- String
- Symbol
复杂类型
- Object
typeof操作符
略
Undefined类型
该类型只有一个值,就是undefined, 左右变量使用let 或者 var声明未赋值的时候,值就是undefined,无需显式声明成undefined
undefined == null // true, 因为undefined是null派生而来
Null类型
该类型同样只有一个值,就是null,表示一个空对象的指针,通常声明一个还没被实际定义的对象数据时,我们可以用null进行填充
Boolean类型
略
Number类型
几点要注意的:
- 八进制数通常(非严格模式,严格模式0o开头)0开头 ,比如 071, 但是只要数值中的数字大于进制范围,该数字会被识别成十进制数字,如079
- 十六进制数字以0x开头,如0xA123, A到F忽略大小写
- 0.1+0.2!=0.3 是因为使用了IEEE754数值造成的,不是语言的问题
- JS中数值范围为Number.MIN_VALUE ~ Number.MAX_VALUE, 超过这个范围只会返回Infinity和-Infinity, 所有数值为无限大的,都不能再用于计算,因为没有对应值可以展示
- NaN: Not a Number, NaN == Nan // false
- 函数isNaN可以接受任何参数,尝试转换成数值,甚至是对象,但是要注意会先尝试调用Object的valueOf方法转换,如果无效,则再调用toString方法
数值转换
以下三个方法可以进行数值转换:
- Number: 参数可传任何数据
- 传布尔值,true为1,false为0
- 传数值直接返回
- null返回0
- undefined返回NaN
- 字符串:
- 传数值字符串则返回对应十进制数值
- 传浮点数字符串返回对应浮点数值
- 如果字符串以0x开头,包含数字和字母,并且单个字母值在A-F闭合区间,则转换成十进制数值
- 空字符(相当于不传参数)返回0
- 除了以上四种字符串传参方式,剩余都返回NaN
- parseInt(arg1,arg2): 参数解释 字符串, 进制
- 在不传arg2的前提下(相当于arg2传了10),传任何 数字 开头的字符串(不包括0x本身),都可以返回对应的整数。但是0x开头的字符串,后续至少要跟一位A-F闭区间的字符,才能转换成对应的十进制展示数否则返回NaN
- 如果传了合理的arg2, 那么arg1的字符串只要在arg2的范围内,则能正确返回对应的十进制展示数,如parseInt(‘kk’,32) // 660
- parseFloat:略
注意Number方法转换参数为数值,和一元操作符 + 相同
String类型
字符串具有length属性
字符字面量:
- \n : 换行
- \t :制表
- \b:退格
- \r:回车
- \f:换页
- \:反斜杠
- \’:单引号(一般用于单引号中嵌套单引号使用)
- \”:双引号,同上
- `:反引号,同上
- \xnn:十六进制开头的数值,如\xAF
- \unnn:以十六进制编码的Unicode字符,如\u03a3 表示 ∑
字符串特点:略
转换成字符串:
- toString方法:
- 数值,布尔值,对象,字符串都有toString方法,null, undefined没有
- 通常toString不用传参数几个返回对应的字符串,如果是数值类型转换,可传进制参数,表明某个数值转换对应进制的结果
- string方法:
- 所有变量都可以用string方法转换成对应字符串
字面量模板和字符串插值:` 和 ${x} , 具备多行字符串快速书写的能力,注意模板会保留对应的空格符
模板字面量标签函数:略
原始字符串:略
Symbol类型
Symbol(符号)类型是ES6新增的数据类型,符号类型是基本数据类型,且符号是唯一的,不可变的。它的主要用途是保证对象的属性名是唯一的,避免发生冲突
基本用法
let sy1 = Symbol()let sy2 = Symbol()typeof sy1 // symbolconsole.log(sy1==sy2) // falselet sy3 = Symbol('sy3')alert(sy3) // TypeError: Cannot convert a Symbol value to a string 注意它是不会隐式转换的alert(sy3.description); // sy3 可以这样alert(sy3.toString()); // 强制转换alert(String(sy3)); // 强制转换// 可以传参,但参数只有描述意义let syFoo = Symbol('这个是Foo')let syBar = Symbol('这个是Bar')console.log(syFoo) // Symbol(这个是Foo)// symbol不能用new创建let myBoolean = new Boolean();console.log(typeof myBoolean); // "object"let myString = new String();console.log(typeof myString); // "object"let myNumber = new Number();console.log(typeof myNumber); // "object"let mySymbol = new Symbol(); // TypeError: Symbol is not a constructor
使用全局符号注册表
前面我们知道,即便对Symbol函数传相同参数,返回的两个symbol实例都不相等,如果你想要一个符号,但是其他地方又可以用到,就用Symbol.for创建
let fooGlobalSymbol = Symbol.for('foo'); // 全局注册表的符号必须使用字符串键来创建console.log(typeof fooGlobalSymbol); // symbollet fooGlobalSymbol = Symbol.for('foo'); // 创建新符号let otherFooGlobalSymbol = Symbol.for('foo'); // 重用已有符号console.log(fooGlobalSymbol === otherFooGlobalSymbol); // truelet localSymbol = Symbol('foo');console.log(fooGlobalSymbol == localSymbol) // false// 创建全局符号let s = Symbol.for('foo');console.log(Symbol.keyFor(s)); // foo// 创建普通符号let s2 = Symbol('bar');console.log(Symbol.keyFor(s2)); // undefinedSymbol.keyFor(123); // TypeError: 123 is not a symbol, 参数必须是符号
使用符号作为属性
let s1 = Symbol('foo'),s2 = Symbol('bar'),s3 = Symbol('baz'),s4 = Symbol('qux');let o = {[s1]: 'foo val'};// 这样也可以:o[s1] = 'foo val'; // 注意 这里和 o['s1'] 是不一样的console.log(o);// {Symbol(foo): foo val}
let s1 = Symbol('foo'),s2 = Symbol('bar');let o = {[s1]: 'foo val',[s2]: 'bar val',baz: 'baz val',qux: 'qux val',[Symbol('a')]:'foo',[Symbol('b')]:'bar',};console.log(Object.getOwnPropertySymbols(o));// [Symbol(foo), Symbol(bar)]console.log(Object.getOwnPropertyNames(o)); // ["baz", "qux"]// 注意使用symbol作为属性,在遍历key的的时候,是不会被打印出来// 利用此特征,可以用它来给object对象写一些私有属性console.log(Object.getOwnPropertyDescriptors(o));// {baz: {...}, qux: {...}, Symbol(foo): {...}, Symbol(bar): {...}}console.log(Reflect.ownKeys(o)); // 注意这个API, ["baz", "qux", Symbol(foo), Symbol(bar)]console.log(o) //{…, Symbol(a): "foo",Symbol(b): "bar"} // 注意这里,symbol直接是一个实例let barSymbol = Object.getOwnPropertySymbols(o).find((symbol) => symbol.toString().match(/bar/)); // 只有这样才能匹配到未标记的symbolconsole.log(barSymbol); // Symbol(bar)
其他
剩余不常用API待补充
- Symbol.iterator
- Symbol.asyncIterator
- Symbol.hasInstance
- Symbol.isConcatSpreadable
- Symbol.match
- Symbol.replace
- Symbol.search
- Symbol.species
- Symbol.split
- Symbol.toPrimitive
- Symbol.toStringTag
- Symbol.unscopables
Object类型
一组数据和功能的集合,创建方法见代码
let obj = new Object()let obj1 = new Object // 不传参数也可以
object实例包含以下属性和方法:
- constructor: 通常指向构造函数
- hasOwnProperty(name):检测当前对象是否包含某个非原型链上的属性
- isPrototypeOf(obj):是否为其他对象的原型对象
- propertyIsEnumerable(propName):检测该对象的某个属性是否可以枚举
- toLocalString()
- toString()
- valueOf()
操作符
一元操作符
位操作符
布尔操作符
乘性操作符
指数操作符
加性操作符
关系操作符
相等操作符
条件操作符
赋值操作符
逗号操作符
语句
if语句
为了其他同事的着想,if后面请用花括号!
do-while语句
至少执行一次循环
for语句
略
for-in语句
通常用于遍历对象属性
let arr = [1,2,3,4]let d = Symbol('d')let obj = {a:1,b:2,c:3,[d]:4,e:null,g:7,f:undefined,}for(let i in arr){ // 注意这里遍历的是数组console.log(i) // 依次打印0,1,2,3 ,注意依次打印的是索引}for(let i in obj){console.log(i) // 注意这里不会遍历到 [d], 并且会按用户顺序返回}
for-of语句
可以理解成专用于数组的遍历语句
let arr = [1,2,3,4]let obj = {a:1,b:2,c:3}for(let i of arr){console.log(i) // 依次打印1,2,3,4}for(let i of obj){ // 注意这里是遍历对象console.log(i) // TypeError: obj is not iterable}
标签语句
标签语句用于给语句加标签,语法如下
start: for (let i = 0; i < count; i++) {console.log(i);}//在这个例子中,start 是一个标签,可以在后面通过 break 或 continue 语句引用。标签语句的典型应用场景是嵌套循环。
不建议使用
break和continue语句
不建议使用,当然在特定循环条件中需要跳出可用break
with语句
永远不要用with语句
switch语句
如果你写了大量的if-else语句,那你需要考虑用switch
函数
函数在任何语言中,都是非常重要的角色, JS的函数使用 function关键字声明,更多详细的内容,会在第十章的时候讲解
function fnName(arg){// ....return // 函数默认是没有返回值的console.log('hello') // return之后的语句不会被执行}
