语法
以下是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 // symbol
console.log(sy1==sy2) // false
let 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); // symbol
let fooGlobalSymbol = Symbol.for('foo'); // 创建新符号
let otherFooGlobalSymbol = Symbol.for('foo'); // 重用已有符号
console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true
let 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)); // undefined
Symbol.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/)); // 只有这样才能匹配到未标记的symbol
console.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之后的语句不会被执行
}