JavaScript总结1

词法结构

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.

数字

  1. JavaScript不区分整数值和浮点数值, 全部数字均以浮点数值表示.
  2. JavaScript中除以0并不报错, 只是返回无穷大(Infinity)/负无穷大(-Infinity). 而0 / 0是没有任何意义的, 因此用NaN表示(NaN表明非数字, 可用isNaN()判断, 例如isNaN("hello")为true).
  3. JavaScript中浮点数依旧存在精度问题:
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

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中对象到字符串的转换经历如下步骤:

  1. 若是对象具备toString()方法, 则调用这个方法. 若是它返回一个原始值, JavaScript将这个值转换为字符串, 并返回这个字符串结果.
  2. 若是对象没有toString()方法, 或者这个方法并不返回一个原始值, 那么JavaScript会调用valueOf()方法, 若是存在这个方法, 则JavaScript调用它. 若是返回值是原始值, JavaScript将这个值转换为字符串, 并返回这个字符串结果.
  3. 否二, JavaScript抛出类型错误.

对象到数字的转换经历如下步骤:

  1. 若是对象具备valueOf()方法, 后者返回一个原始值, 则JavaScript将这个原始值转换为数字.
  2. 不然, 若是对象具备toString()方法, 后者返回一个原始值, 则JavaScript将其转换并返回
  3. 不然, 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]
相关文章
相关标签/搜索