1. JavaScript程序是用Unicode字符集编写的.javascript
let s = '你好' // true console.log(s === '你好') // 你好 console.log(s)
2. JavaScript区分大小写, 而HTML不区分大小写.(我的推荐命名JS变量, 使用驼峰式命名)java
3. JavaScript会忽略程序中标识之间的空格, 可是良好的代码风格相当重要.web
4. JavaScript支持"//"和/*...*/两种注释, 可是注释中不可嵌套注释.正则表达式
5. 直接量: 程序中直接使用的数据值, 可简单理解为"直接分配内存地址的变量", 例如数值, 字符串, 布尔型和正则表达式直接量(/javascript/gi).数组
6. JavaScript的标识符必须以字母, 下划线或者美圆符号开始, 后续跟字母, 数字, 下划线或者美圆符号.函数
7. JavaScript中关于填补分号的规则: 只要在缺乏了分号就没法正确解析代码的时候, JavaScript才会填补分号. 我的习惯为不加分号(在ES6的语法下)spa
JavaScript的数据类型分为两类: 原始类型和对象类型. JavaScript的原始类型包括数字, 字符串和布尔值. 而对象是属性的集合, 每一个属性都由"名/值对"组成.指针
咱们一般会判断一个变量是否为数字,字符串,布尔值, 函数或者对象. 最简单的一个方法是使用typeof:code
// "number" console.log(typeof 1) // "string" console.log(typeof 'hello') const f = () => {} // function console.log(typeof f) // object console.log(typeof [])
但使用typeof没法判断数组, 这时候咱们须要使用Array.isArray:对象
// true console.log(Array.isArray([]))
存在一种特殊的状况, 不管传进来的参数是什么, 咱们须要的是一个数值. 这时候通常使用parseInt/parseFloat进行转换后, 不可以使用typeof来判断(typeof NaN === "number"), 应该使用isNaN()来判断是否为NaN.
而针对对象, 因为是无序哈希集合, 则工做中常常会碰到以下状况:
1) 获取全部的keys: 使用Object.keys():
const dst = { name: 'xx', age: 33, } // ['name', 'age'] console.log(Object.keys(dst))
2) 对对象进行遍历, 可以使用in, 若是须要对可迭代对象进行变量, 则须要使用of:
function* foo() { yield 1 yield 2 } let f = foo() // 1 // 2 for (let k of f) { console.log(k) }
3) 对一个变量进行深层次的获取, 可能会写出这样的代码:
dst.country && dst.country.province && dst.country.province.name
这时候, 要么定义一个函数来获取, 要么须要一层层判断.
JavaScript中有两个特殊的原始值: null和undefined, 它们不是数字,字符串和布尔值. 它们一般分别表明了各自特殊类型的惟一的成员.原始类型, null和undefined均为不可变类型.
针对null和undefined, 存在以下的坑:
let a = undefined let b = null a = a + '' b = b + '' // string undefined console.log(typeof a, a) // string null console.log(typeof b, b)
这可能并不是咱们的本意. 实际项目中不多会纠结于null/undefined, 通常将它们当作false便可.
数组是特殊的集合, 它的下标索引即为key值, 而对象的key为字符串.
let arr = [11, 22, 33] // 0 -- 11 // 1 -- 22 // 2 -- 33 for (let k in arr) { console.log(k, '--', arr[k]) } // true console.log(arr['1'] === arr[1])
函数是对象, 而箭头函数的引入, 则方便了函数做为参数进行使用:
const f1 = (num) => ++num const f2 = (num) => () => f1(num) // 2 console.log(f2(1)())
JavaScript解释器有本身的内存管理机制, 能够自动对内存进行垃圾回收.
ES6中引入块级做用域, 尽可能使用let/const, 放弃var.
let x = 0.3 - 0.2 let y = 0.2 - 0.1 x == y -->false x == 0.1-->false y == 0.1-->true
字符串的使用
let s = "hello world" s.charAt(0) ==> "h": 第一个字符 s.charAt(s.length - 1) ==> "d": 最后一个字符 s.substring(1, 4) ==> "ell": 第2~4个字符 s.slice(1, 4) ==> "ell": 同上 s.slice(-3) ==> "rld": 最后三个字符 s.indexOf("l") ==> 2: 字符l首次出现的位置 s.lastIndexOf("l") ==> 9: 字符l最后出现的位置 s.indexOf("l", 3) ==> 3: 在位置3及以后首次出现字符l的位置. s.split(" ") ==> ["hello", "world"]: 分割字符串 s.replace("h", "H") ==> "Hello world": 替换 s.toUpperCase() ==> "HELLO WORLD": 转换成大写
转换为false的变量: undefined, null, NaN, 0, -0, ""
在工做中, 常常犯以下的错误, 例如判断一个变量是否为false:
if (a) {}
但有时候没考虑到a为空数组/空对象的状况. 因此, 针对数组来讲, 应该这样判断:
if (Array.isArray(a) && a.length === 0) {}
但空对象并很差判断, 若是咱们仅仅判断:
if (typeof a === 'object' && Object.keys(a).length === 0) {}
须要考虑到万一a继承了某个类的属性怎么办? 因此更好的方法应该判断某个属性是否在a中:
if ('name' in a) {}
null表明空指针, 一般用来表示数字, 字符串和对象的"无值状态"
undefined表明未初始化.
全局属性: 好比undefined, Infinity和NaN
全局函数: 好比isNaN(), parseInt()和eval()
构造函数: 好比Date(), RegExp(), String(), Object()和Array()
全局对象: 好比Math和JSON
对于字符串, 如下代码是正确的:
let s = "hello world" let word = s.substring(1, 4)
既然字符串不是对象, 它为何会有substring方法呢? 由于引用字符串s的属性, JavaScript就会将字符串经过调用new String(s)的方式装换成对象, 一旦属性引用结束, 这个新建立的对象就会销毁(同理于Number()和Boolean()):
let s = "test" s.len = 4 let t = s.len t ==> undefined
而:
"hello" == new String("hello") ==> true "hello" === new String("hello") ==> false
原始值: undefined, null, 数字, 布尔值, 字符串. 它们均不可改变.
对象: 数组和函数, 可改变.
比较两个变量, 除非特地, 不然尽可能使用"==="来进行比较. 而对象的比较毫无心义.
let a = 1 let b = '1' // true console.log(a == b) // false console.log(a === b)
对象的引用是一个大问题, 例如咱们可能会写以下的代码:
let arr = [1, 2] let b = arr b.push(3) // [1, 2, 3] console.log(arr)
咱们须要的是一个副本, 而非引用. 这时候, 应该使用Object.assign:
let arr = [1, 2] let b = Object.assign([], arr) b.push(3) // [1, 2 ] console.log(arr)
JavaScript的类型转换本质是: 解释器须要什么类型, 则将根据须要将变量转换为其类型.
值 | 字符串 | 数字 | 布尔值 | 对象 |
undefined null |
"undefined" "null" |
NaN 0 |
false false |
throws TypeError throws TypeError |
true false |
"true" "false" |
1 0 |
new Boolean(true) new Boolean(false) |
|
"" "1.2" "one" |
0 1.2 NaN |
false true true |
new String("") new String("1.2") new String("one") |
|
0 -0 NaN Infinity -Infinity 1 |
"0" "0" "NaN" "Infinity" "-Infinity" "1" |
false false false true true true |
new Number(0) new Number(-0) new Number(NaN) new Number(Infinity) new Number(-Infinity) new Number(1) |
|
{} [] [9] ['a'] function(){} |
后面解释 "" "9" 使用join方法 后面解释 |
后面解释 0 9 NaN NaN |
true true true true true |
转换和相等性
进行"=="判断时, JavaScript会进行类型转换.
null == undefined ==> true "0" == 0 ==> true
这里类型转换表明的意思是: a == b, 则a转换为b类型, 或者b转换为a类型, 再次进行比较. 因此对于null == undefined, 本质上是undefined转换为一个Object, 而后在和null进行比较.
而"0" == 0, 是将数字0转换为字符串"0", 而后再进行比较.
但能够成功进行类型转换, 不必定表示它们相等, 如undefined可转换为false, 但undefined == false的结果为false.
在比较时候, 尽可能使用"==="而非"==".
显示类型转换
JavaScript在须要字符串状况下, 会将变量转换为字符串; 其次, 在须要数字状况下, 会将变量转换为数字.
Number类定义的toString()方法能够接收表示转换基数的可选参数. 若是不指定此参数, 转换规则将是基于十进制:
let n = 17 n.toString() ==> "17" n.toString(2) ==> "10001" n.toString(8) ==> "21" n.toString(16) ==> "11"
toFixed(): 根据小数点后的指定位数将数字转换为字符串, 它从不使用指数计数法.
toExponential(): 使用指数计数法将数字转换为指数形式的字符串, 其中小数点前只有一位, 小数点后的位数则由参数指定.
toPrecision(): 根据指定的有效数字位数将数字转换成字符串. 若是有效数字的位数少于数字部分的位数, 则转为为指数形式.
let n = 123456.789 n.toFixed(0) ==> "123457" n.toFixed(2) ==> "123456.79" n.toFixed(5) ==> "123456.78900" n.toExponential(1) ==> "1.2e+5" n.toExponential(3) ==> "1.235e+5" n.toPrecision(4) ==> "1.235e+5" n.toPrecision(7) ==> "123456.8" n.toPrecision(10) ==> "123456.7890"
parseInt(): 尽量的将字符串转换为整数, 可接收第二个可选参数, 这个参数指定数字转换的基数.
parseFloat(): 尽量的将字符串转换为浮点数.
对象转换为原始值
toString(): 返回一个反映这个对象的字符串.
valueOf(): 若是存在任意原始值, 它就默认将对象转换为表示它的原始值.
JavaScript中对象到字符串的转换经历如下步骤:
对象到数字的转换经历如下步骤:
因为ES6中class的引入, 再也不使用函数当作一个对象来建立实例了. 而函数仅仅单纯起到函数的做用, 而且将函数当作一个变量进行调用:
const func = () => console.log('hello world') func()
若是存在相似class的需求, 例如用到继承, 实例等, 可考虑引入class:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes
1. JavaScript运算符一般会根据操做数进行类型转换, 因此"3" * "5"是合法的, 为数字15.
若是想获取一个数组的最大值, 最小值和平均值, 有个通用的写法为:
const arr = ['1', '3', 2, '44', 5, '222'] const max = arr.reduce((x, y) => x - y > 0 ? x : y) const min = arr.reduce((x, y) => x - y > 0 ? y : x) const avg = arr.reduce((x, y) => parseInt(x) + parseInt(y)) / arr.length // 222 1 46.17 console.log(max, min, avg.toFixed(2))
备注: web开发中常常遇到字符串型数值.
这里之因此使用x - y > 0是由于"-"会进行数值运算.
2. 一般使用"+"来将数组转换为字符串, 或者将字符串数值转换为数值:
let arr = [1, 2, 3] // 1,2,3 console.log(arr + '') // number console.log(typeof +"3")
3. in用于判断属性是否存在与对象实例+原型中:
let point = { x: 1, y: 2, } // true console.log('x' in point) // true console.log('toString' in point) // false console.log('xx' in point)
4. instanceof用于判断左边对象是否为右边类的实例.
const d = new Date() // true console.log(d instanceof Date) // true console.log(d instanceof Object) // false console.log(d instanceof RegExp)
5. typeof运算符用于判断对象的类型:
x |
typeof x |
undefined |
"undefined" |
null |
"object" |
true或false |
"boolean" |
任意数字或NaN | "number" |
任意字符串 | "string" |
任意函数 | "function" |
任意内置对象(非函数) | "object" |
任意宿主对象 | 由编译器自身决定 |
6. delete用于删除一个对象的属性, 对数组来讲至关于赋值undefined:
let o = {x: 1, y:2} delete o.x o ==> Object {y: 2} let arr = [11, 12, 13] delete arr[1] arr ==> [11, undefined × 1, 13]