JS知识体系

415 阅读14分钟

Script元素

属性

  1. async:立即下载、立即执行、不阻塞页面加载,只能用于外部脚本,异步脚本不可修改DOM
  2. defer:立即下载、页面加载完成执行,全部在DOMContentLoaded之前执行
  3. crossorigin:是否允许跨域,anonymous为不携带跨域请求头,use-credentials为携带请求头
  4. integrety:比对接受到的资源和指定的加密签名以验证完整性,不一致则报错脚本不执行
  5. src:设置资源url
  6. type:一般为'text/javascript',值为module被当成模块,才可使用import/export

特点

  • 脚本从上往下执行,阻塞页面渲染
  • script使用了外部脚本就不能包含行内脚本了,否则行内脚本被忽略

动态脚本

动态脚本默认是异步的,但不是所有浏览器都支持async属性,为了统一加载脚本行为,只能将其设为同步

let script = document.createElement('script')
script.src = 'xxx.js'
script.async = false
document.body.appendChild(script)

动态脚本资源对浏览器预加载不可见,需要手动预加载

<link rel="preload" ref="xxx.js"></link>

语言基础

变量

  • var函数作用域,let和const块级作用域
  • var有变量提升,let和const有暂时性死区
  • var声明的全局变量在window对象上,let和const声明的不会
  • const声明必须立即初始化且不能修改值的引用

const优先,let次之,不建议var

数据类型

typeof操作符

数据类型
Undefined'undefined'
Number'number'
String'string'
Boolean'boolean'
Object或Null'object'
Function'function'
Symbol'symbol'

Undefined

声明但未赋值的变量值为undefined
未声明的变量和未初始化的变量typeof结果都为undefined,因此声明变量时就初始化是必要的

Null

null表示空对象指针,定义对象变量用null初始化

Boolean

所有值都可以用Boolean()转为布尔值,0、''、false、null、undefined和NaN结果false,其他结果为true

Number

Number.MIN_VALUENumber.MAX_VALUE表示最大值和最小值,isFinite(number)是否有限,true有限

isNaN(值)是否转化为NaN

Number(值)的规则:

  • true转1,false转0
  • undefined转NaN
  • null转0
  • number返回本身
  • 只包含数字的字符串和""返回数值,其他NaN
  • 对象先调valueOf(),按上述规则转的结果为NaN则调用toString()

parseInt(值,参数1的进制数)数值、+和-开头的截取到非数值位置,否则NaN

parseFloat(值)数值、+和-开头的截取到非数值或无效浮点数位置,否则NaN

String

只读属性length表示字符串长度。

toString(结果的进制值)除了undefined和null都有此方法,作用和String()一致

Symbol

TODO

Object

Object类公共方法:

  • Constructor:当前对象的构造函数
  • hasOwnProperty(属性名):当前属性是否在对象的实例上
  • a.isPrototypeOf(b):a是否是b的原型对象
  • propertyIsEnumerable(属性名):属性是否可用for-in枚举
  • toString()
  • toLocaleString()
  • valueOf()

操作符

一元操作符

先调用Number()在运算

位运算符

按位非~:结果是数值的反码,结论是负数-1
按位与&:对应位都为1才为1
按位或|:对应位都为0才为0
按位异或^:对应位都为0或1则为1

布尔运算符

逻辑非!:先调用Boolean()再取反
逻辑或||:先调Boolean(),遇到true则返回该操作数
逻辑与&&:先调用Boolean(),遇到false则返回该操作数

加减乘除运算符

+-*/%运算操作数先调用Number(),有操作数是NaN则结果是NaN
+有一边是字符串则是拼接

关系运算符

先调用Number(),再比较大小。
两个操作数都是字符串则比较字符编码。

相等运算符

==运算符规则:

  • 会进行隐式类型转换
  • undefined==null
  • 对象比较是否是同一个对象

===操作符执行严格相等比较

语句

for-in语句只循环对象实例和原型中非Symbol属性

for(let 属性名 in 对象){
    循环体
}

for-of语句会按照可迭代对象的next()方法产生值的顺序迭代元素

for(let 属性名 of 可迭代对象){
    循环体
}

label语句可配合break和continue跳出执行

start: for (var i = 0; i < count; i++) {
  alert(i);
}

变量、作用域和内存

原始值和引用值

原始值的变量按值访问,引用值的变量按引用访问

复制原始值是把变量副本给新的变量,新旧变量互不干扰;复制引用值是把变量指针给新变量,新旧变量相互映射

函数参数都是按值传递的

function setName(obj){
	obj.name = "zzz";
}
let person = new Object();
setName(person)
console.log(person.name); // 'zzz',函数参数是按值传递的,所以obj的值是一个地址的复制值,但是修改和访问引用变量时是按引用访问的,所以修改后还是会映射到原有值
function setName(obj){
	obj.name = 'zzz'
	obj = new Object();
	obj.name = 'zcw'
}
let person = new Object();
setName(person)
console.log(person.name); // 'zzz',如果函数传参是按引用传递的,那么修改obj的值时,会映射到变量person的值,但实际没有影响,所以函数传参是按值传递的

执行上下文和作用域

每个上下文都有变量对象,上下文中定义的变量和函数都存在这个变量对象上。

当代码执行流进入函数时,函数的上下文会被推到上下文栈中。函数执行结束,上下文栈弹出函数上下文,控制权返还给之前的执行上下文,函数上下文此时销毁。

上下文中的代码执行时,会创建变量对象的作用域链(决定各级上下文中的代码在访问变量和函数时的顺序),函数上下文的变量对象是AO活动对象(初始只有arguments对象)

基本引用类型

Date

new Date()不传参数创建当前日期的日期对象,传一个毫秒数表示创建该时间戳的日期对象。

Date.parse()传入一个表示日期的字符串,返回对应时间戳

Date.parse('4/27/2021')
new Date('May 23,2021') // 会自动调用Date.parse('May 23,2021')

Date.UTC()传入年,月,日,时,分,秒和毫秒,返回对应的时间戳。年月必传。

Date.now()返回执行方法时的时间戳

RegExp

模式

  • g:全局,查找字符串的全部匹配项
  • i:不区分大小写
  • m:多行匹配
  • y:粘附模式,只查找正则实例的lastIndex属性开始的字符串部分
  • u:启用unicode匹配
  • s:dotAll模式,表示元字符.匹配任何字符(包括\r或\n)

RegExp实例属性

  • global:是否设置了g标记
  • ignoreCase:是否设置了i标记
  • unicode:是否设置了u标记
  • sticky:是否设置了y标记
  • multiline:是否设置了m标记
  • dotAll:是否设置了s标记
  • lastIndex:字符串在下一次搜索开始位置
  • source:正则表达式的匹配规则
  • flags:正则表达式的模式
let pattern = /\[bc\]at/i
console.log(pattern.global) // false
console.log(pattern.ignoreCase) // true
console.log(pattern.multiline) // false
console.log(pattern.lastIndex) // 0
console.log(pattern.source) // "\[bc\]at"
console.log(pattern.flags) // "i"

RegExp实例方法

实例.exec(字符串):寻找匹配项,如果不设置全局或粘贴,则每次捕获第一项结果

let text = 'mom and dad and baby'
let pattern = /a/gi
let matches = pattern.exec(text) // ["a", index: 4, input: "mom and dad and baby", groups: undefined]
matches = pattern.exec(text) // ["a", index: 9, input: "mom and dad and baby", groups: undefined]

实例.test(字符串):如果参数与模式匹配,返回true

RegExp构造函数属性

  • input:最后搜索的字符串
  • lastMatch:最后匹配的文本
  • lastParen:最后匹配的捕获组
  • leftContext:input字符串中出现在lastMatch左边的文本
  • rightContext:input字符串中出现在lastMatch右边的文本
let text = 'this has been a short summer'
let pattern = /(.)hort/g

if(pattern.test(text)){
    console.log(RegExp.input) // this has been a short summer
    console.log(RegExp.leftContext) // this has been a
    console.log(RegExp.rightContext) // summer
    console.log(RegExp.lastMatch) // short
    console.log(RegExp.lastParen) // s
}

原始包装类型

当在原始类型上调用方法时,会执行以下三步:

  1. 创建基本包装类型的实例
  2. 调用实例上的方法
  3. 立即销毁实例
'abc'.substr(1)
// 等同于
let s = new String('abc')
s.substr(1)
s = null

包装类型的特点:

  1. 包装类型调用完方法就销毁
  2. 包装类型typeof都是'object',所以转为布尔值都为true

Boolean

布尔包装类型的valueOf()返回true和false,toString()返回'true'和'false'
布尔包装类型调用instanceOf Boolean返回true,布尔基本类型调用这个返回false

Number

toFixed(小数位数):返回指定小数位数的字符串,自动舍入
toExponential(指定小数位数):返回包含指定小数位数的科学计数法字符串
toPrecision(指定位数):根据指定位数来决定返回科学计数法或者小数点数值
Number.isInteger(数值):可通过此方法判断数值是否为整数,是整数返回true,1.00会返回true

String

字符方法

charCodeAt(索引):返回索引位置的字符编码
charAt(索引):返回索引位置的字符
fromCharCode(任意个unicode编码):将编码转为字符串

操作方法

concat(任意个字符):将原串的副本与参数拼接
slice(开始位置,结束位置):返回开始位置到结束位置之前的子串,传入负数则加上字符长度
substring(开始位置,结束位置):返回开始位置到结束位置之前的子串,传入负数转为0
substr(开始位置,n):返回开始位置的n个字符,第一个参数为负数则加上字符长度,第二个参数为负数转为0

位置方法

indexOf(字符串,开始位置):从开始位置开始搜索字符串,返回位置,没找到返回负数
lastIndexOf(字符串,开始位置):从开始位置往前查找,返回位置,没找到返回负数

包含方法

startsWith(字符串,开始位置):开始位置是否以参数一开头。 endsWith(字符串,结束位置):结束位置是否以参数一结尾。 includes(字符串,开始位置):从开始位置到字符结束,是否包含参数一字符。

trim方法

trim():创建一个字符串副本,删除前后所有空格。 trimLeft():删除副本左边空格。 trimRight():删除副本右边空格。

复制方法

repeat(n):将字符复制n次并拼接

let s = 'na'
s.repeat(5) // nanananana

padStart(长度,填充字符):若字符小于长度,则在开头填充参数二字符,没有参数二则填充空格。 padEnd(长度,填充字符):若字符小于长度,则在结尾填充参数二字符,没有参数二则填充空格。

字符串解构

字符串原型上暴露了@@iterator方法,可以迭代字符串每个字符,所以可用for-of来遍历。

let message = 'ab'
let StringIterator = message[Symbol.iterator]()

console.log(StringIterator.next()) // {value:'a',done:false}
console.log(StringIterator.next()) // {value:'b',done:false}
console.log(StringIterator.next()) // {value:undefined,done:true}

for(const s of 'abcde'){
    console.log(s)
}
字符串大小写转换

toLowercase()和toUpperCase()

字符串匹配方法

match(正则表达式):返回值与exec相同,是一个数组,第一项是匹配到的字符串,其他两项是index和input
search(正则表达式):从左往右匹配,返回第一个匹配到的位置索引,没匹配到返回-1
replace(正则表达式,替换字符或函数):用第二个参数来替换匹配到的字符

function htmlEscape(text){
    return text.replace(/[<>"&]/g,function(match,pos,originalText){
        switch(match){
            case "<":
                return "&lt;"
            case ">":
                return "&gt;"
            case "&"
                return "&amp;"
            case "\"":
                return "&quot;"
        }
    })
}

htmlEscape("<p class=\"greeting\">Hello world!</p>") // "&lt;p class=&quot;greeting&quot;&gt;Hello world!</p>"

split(字符串或匹配正则,数组长度):根据第一个参数的结果来分割字符,返回的数组长度不会超过参数二

let colorText = 'red,blue,green,yellow'
let colors1 = colorText.split(',') // ['red','blue','green','yellow']
let colors2 = colorText.split(',',2) // ['red','blue']
let colors3 = colorText.split(/[^,]+/) // ['', ',', ',', ',', '']

集合引用类型

Object类型

创建Object实例的方式:new Object(){}
对象属性可通过.语法或者['属性名']来获取

Array类型

创建Array实例的方式:new Array(多个元素或着一个数组长度)[]

Array静态方法

Array.from()将类数组结构转为数组结构。第一个参数是类数组对象(即可迭代的对象)或者有length属性和可检索元素的对象,第二个参数是一个可选的映射函数,第三个参数用于指定this值(箭头函数中不适用)

const a1 = [1,2,3,4]
const a2 = Array.from(a1) // 数组浅拷贝

const arrayLikeObject = {
    0: 0,
    1: 1,
    2: 2,
    3: 3,
    length: 4
}
console.log(Array.from(arrayLikeObject)) // [1,2,3,4]

const a3 = Array.from(a1,function(x){return x**this.exponent},{exponent: 2})

Array.of()将一组参数转化为数组,用于替代ES6之前的Array.prototype.slice.call(arguments)这种写法

Array.of(1,2,3,4) // [1,2,3,4]

检测数组

在只有一个全局对象的情况下(即网页没有多个框架),用instanceof即可,如果有多个全局对象,则需要用Array.isArray(value)

迭代器方法

keys()返会数组索引的迭代器,values()返回数组元素的迭代器,entries()返回索引/值对的迭代器

const a = ['foo','bar','baz','qux']
const aKeys = Array.from(a.keys()) // [0,1,2,3]
const aValues = Array.from(a.values()) // ['foo','bar','baz','qux']
const aEntries = Array.from(a.entries()) // [[0,'foo'],[1,'bar'],[2,'baz'],[3,'qux']]

复制和填充方法

fill(填充字符,开始索引,结束索引):向数组的开始索引至结束索引插入填充字符,没有结束索引填充到结束,负数索引加上数组长度,超出索引边界、零长度和方向相反则忽略

const zeroes = [0,0,0,0,0]
zeroes.fill(6,3,4) // [0,0,0,6,0]
zeroes.fill(6,-2,-1// [0,0,0,6,0]
zeroes.fill(6,10,15) // 超出边界,忽略
zeroes.fill(6,4,2) // 方向相反,忽略
zeroes.fill(6,4,10) // [0,0,0,0,6]部分可用部分填充

copyWithin(填充开始索引,开始复制索引,结束复制索引)浅复制指定索引内的内容,然后填充到指定索引位置

转换方法

toLocaleString()
toString():返回数组每项以逗号拼接的字符串
valueOf():返回数组本身
join(拼接字符):将数组用参数分隔拼接成字符串,不传则为逗号

操作方法

concat():受任意个参数,将其添加到源数组副本的后面,参数如果是数组,会自动打平,可以设置Symbol.isConcatSpreadable为false来禁止强制打平数组

let colors = ['red','green','blue']
let colors2 = colors.concat('yellow',['black','brown'])
console.log(colors) // ['red','green','blue']
console.log(colors2) // ['red','green','blue','yellow','black','brown']

let moreNewColors = {
    [Symbol.isConcatSpreadable]: false
    length: 2,
    0: 'pink',
    1: 'cyan'
}
let colors3 = colors.concat(moreNewColors)
console.log(colors3) // ['red','green','blue',['pink','cyan']]

slice(开始索引,结束索引):源数组的副本从开始索引开始截取,直到结束索引,返回截取的数组
splice(开始索引,删除长度n,添加的值):原数组从开始索引位置开始删除,删除n个项,然后将后面的值插入给数组,返回删除的数组

栈方法

push()接受任意数量参数添加到末尾,返回数组长度
pop()删除数组最后一项,返回被删除的项

队列方法

unshift()接受任意数量参数添加到开头,返回数组长度
shift()删除数组第一项,返回被删除的项

排序方法

reverse()将数组反转

sort()将数组每项调用String()进行排序,可接受一个比较函数,形参a和b表示数组中靠前的项和靠后的项,如果需要交换位置,则返回正数,否则返回负数

let values = [0,1,5,10,15]
values.sort(function(a,b){
    return a-b // 如果a>b,则a-b为正数,则交换位置,所以是升序排列。如果是return b-a,则是降序
    
})

搜索和位置方法

严格相等(===)

indexOf(要查找的元素,开始查找的位置)从头或者从参数二位置开始查找元素,找到返回索引,没找到返回-1
lastIndexOf(要查找的元素,开始查找的位置)从最后一项或者参数二位置开始往前查找元素,找到返回索引,没找到返回-1
includes(要查找的元素,开始查找的位置)从头或者参数二位置开始查找元素,找到返回true,没找到返回false

断言函数

find(断言函数)数组每项调用断言函数,如果断言函数返回真值则表示匹配,返回匹配的项

const evens = [2,4,6]
evens.find((item,index,array)=>{
    console.log(item,index.array)
    return item === 4
})

findIndex(断言函数)数组每项调用断言函数,如果断言函数返回真值则表示匹配,返回匹配的项的索引

归并方法

reduce(归并函数,归并初始值)从左往右迭代数组每一项,将上一次的结果作为下一次调用的初始值

let values = [1,2,3,4,5]
let sum = values.reduce((prev,cur,index,array)=>prev+cur)
console.log(sum) // 15

reduceRight(归并函数,归并初始值)从右往左迭代数组每一项,将上一次的结果作为下一次调用的初始值

迭代方法

每个迭代方法接受两个参数:以每一项为参数运行的函数和函数this对象

every()对数组每一项都运行函数,如果每一项函数都返回true,则返回true
some()对数组每一项都运行函数,如果有一项函数都返回true,则返回true
filter()对数组每一项都运行函数,函数返回true的项组成数组后返回
map()对数组每一项都运行函数,返回由每次函数调用的结果构成的数组
forEach()对数组每一项都运行函数,没有返回值

持续更新中...