一、异步加载script两种方式
<script defer></script>
<script async></script>
前者是异步加载,等待页面加载解析后再执行;后者是加载完成后立即执行,且多个async的script脚本执行次序不一定。
二、特别概念
1、xhml
xhtml是将html作为xml的应用重新包装的结果。和js不同的是,使用时要加:
<script tpye="text/javascript"></script>
2、noscirpt
浏览器无法解析script标签时会显示其中的内容。
3、严格模式
严格模式时ES5提出的一种概念,用于解决ES3的不规范写法处理,对于不安全的活动将会抛出错误。使用方法为:
function A() {
"use strict";
函数内部代码
}
三、变量
1、var let const区别
①var存在变量提升,let const不存在变量提升
②var作用域为函数作用域,let const作用域为块作用域
③在全局环境中进行声明,var变量会挂载到window上,let const不会
④const变量需要初始化,let var不需要;const初始化变量无法修改,若为数组或者对象则可以修改
⑤var同一个变量不能重复声明,let const可以重复声明同一变量
特别注意:var在for循环中会发生泄露,但let不会;因为let作用域为块作用域
2、数据类型
简单数据类型:Undefined、Boolean、String、Number、Symbol、Null
复杂数据类型:Object(、Array、Function)
数据类型转换:
①Boolean()函数
数据类型 | 转为true | 转为false |
String | 非空字符 | “” |
Number | 非零数字 | 0、NaN |
Object | 任意对象(空对象{}也会转为true) | null |
Undefined | N/A(不存在) | undefined |
②Number()函数
数据类型 | 转换规则 |
Boolean | false转为0,true转为1。 |
Number | 直接返回 |
null | 返回0 |
undefined | 返回NaN |
字符串 | 如果是空字符串,返回0;特别情况返回NaN |
对象 | 调用valueOf()方法,并按照上述规则转换返回的值;若转化结果为NaN,则再调用toString()方法,再按照字符串的规则来转换。 |
3、数据类型的判断
(1)typeof
①基本数据类型中:Number,String,Boolean,undefined 以及引用数据类型中Function ,可以使用typeof检测数据类型,分别返回对应的数据类型小写字符。
②用typeof检测构造函数创建的Number,String,Boolean都返回object
③基本数据类型中:null 。引用数据类型中的:Array,Object,Date,RegExp。不可以用typeof检测。都会返回小写的object
(2)instanceof
判断右边的原型是否在左边的原型链上。
(3)constructor
var a=123
var b=true
a.constructor==Number//返回true
//因为a没有constructor,但a的原型对象上有constructor,因此返回true
b.constructor==Boolean//true
(4)Object.prototype.toString.call()
4、全等和三等(==和===)
(1)==
如果有操作数是boolean型,两者均转化为数值再比较。
如有一个是字符串,另一个是数值,则两者均转为数值。
如有NaN,则一定返回false。NaN==NaN也返回false
null和undefined相等,且不会强制转换。
对象进行比较则看两者是否为同一对象;如有一个是对象,另一个操作数不是,则调用valueOf()方法转化对象。
(2)===
不转换操作数。
5、深拷贝与浅拷贝(变量存储)
原始值存储在栈内存中,引用值(object这些)存储在堆内存中。
(1)深浅拷贝的区别
浅拷贝:单纯复制了地址
深拷贝:在内存中新开辟了一块空间,存放相同的数据
(2)深拷贝的实现
①JSON.parse(JSON.stringfy(obj))
缺点:
会忽略 undefined
会忽略 symbol
不能序列化函数
不能解决循环引用的对象
②Object.assign(targetobj, srcobj)
缺点:对于一级属性是深拷贝,对于二级属性是浅拷贝。
③递归拷贝
四、作用域和内存
1、执行上下文
执行上下文就是作用域。任何变量都存在于某个执行上下文中,这个上下文决定了变量的生命周期,以及它们可以访问代码的哪些部分。
执行上下文分为:全局上下文、函数上下文和块级上下文。
当访问到某个函数时,改函数的函数上下文会被推入上下文栈中,代码执行完毕后被销毁。
代码执行流每进入一个新上下文,都会创建一个作用域链,用于搜索变量和函数。
3、垃圾回收
标记清理和引用计数
五、String常用方法
1、charAt()
方法内部为数字,表示第几个位置的字符
2、charCodeAt()
查看指定码元的字符编号
3、length
查看字符串的长度
4、操作方法
方法 | 作用 |
concat() | str1.concat(str2),拼接字符串;返回新字符串 |
slice(起始位置,终止位置) | 切割字符串,返回新字符串 |
substr(起始位置,截取长度) | 切割字符串,返回新字符串 |
substring(起始位置,终止位置) | 切割字符串,返回新字符串 |
5、位置方法
方法 | 作用 |
indexOf() | 正向搜寻第一个出现的位置,找不到返回-1 |
lastIndexOf() | 反向搜寻第一个出现的位置,找不到返回-1 |
6、包含方法
方法 | 作用 |
startsWith() | 以某段字符串开始 |
endsWith() | 以某段字符串结束 |
includes() | 是否包括 |
7、trim()方法
将字符串前后的空格去掉
8、repeat()方法
repeat()方法中为数字,表示重复多少次,返回新字符串。
9、大小写方法
toLowerCase()和toUpperCase()
toLocalLowerCase()和toLocalUpperCase()
10、匹配方法
match()方法,里面为正则表达式,返回一个数组,数组的第一项是第一个匹配到的子串位置
search()方法,里面为正则表达式,返回第一个字符在字符串中的位置
replace()方法,两个参数;第一个为字符串或者正则表达式,第二个为字符串;若为字符串,则只替换一次;若为正则表达式且带有g全局标志,则全部替换
六、Array方法
1、创建数组
①:使用数组字面量
②:Array.from():用于将类数组结构转化为数组
③:Array.from(arg1,arg2,arg3,...):用于将一系列参数转化为数组
2、监测数组的四种方法
a.constructor==Array//true
Array.isArray(a)//true
Object.prototype.toString.call(a)//true
a instanceof Array//true
typeof a//'object'
3、迭代器方法
①a.keys()
②a.values()
③a.entries()
4、复制和填充方法
①a.fill(arg) 用arg填充数组a
②a.copyWithin()
5、栈和队列方法
①a.push() a.pop()
②a.shift() a.unshift(arg)
6、排序方法
①a.reverse() 数组反转
②a.sort(function) 数组排序
a.sort():将数组中每一项使用String函数进行转换,在进行升序排序
升序排序:a.sort((a,b)=> a-b)
降序排序:a.sort((a,b)=>b-a)
特别注意:sort()源码中,如果数组长度不超过10用插入排序;数组长度大于10用快排。
7、操作方法
slice(startIndex,endIndex):返回切割后的新数组
concat(newArr):返回拼接后的数组
splice(startIndex,deleteNum,arg1,arg2,...):从startIndex开始删除deleteNum个元素,再将arg1、arg2等插入进去。可实现删除、插入、替换等功能。
8、搜索和位置方法
方法 | 作用 |
a.indexOf() | 正向搜索第一个匹配元素的位置 |
a.lastIndexOf() | 反向搜索第一个匹配元素的位置 |
a.includes() | 判断数组中是否包含某元素 |
a.find((element,index.array)=>{}) | 寻找满足条件的第一个元素 |
a.findIndex((element,index.array)=>{}) | 寻找满足条件的第一个元素索引 |
9、迭代方法
方法 | 作用 |
arr.every((item,index,array)=> { } ) | 数组中每一项都满足条件,则返回true;只要有一项不满足,则返回false |
arr.some((item,index,array)=> { } ) | 数组中只要有一项满足条件就返回true |
arr.filter((item,index,array)=> { } ) | 将数组中满足条件的项组成新数组并进行返回 |
arr.forEach((item,index,array)=> { } ) | 对数组中每一项进行操作,无返回值 |
arr.map((item,index,array)=> { } ) | 对数组中每一项进行操作,并返回新数组 |
10、迭代方法
方法 | 作用 |
reduce((pre,cur,index,array)=> {}) | 遍历数组每一项并进行归并 |
reduceRight((pre,cur,index,array)=> v | 从右遍历数组每一项并进行归并 |
11、数组去重
const a = [1, 2, 4, 1, null, null, NaN, undefined, {}]
console.log(a);
// 方法一
const a1 = new Set(a)
console.log(Array.from(a1));
// 方法二
console.log(a.filter((item, index, array) => a.indexOf(item) == index));
// 方法三
const a2 = []
a.forEach(item => { !a2.includes(item) && a2.push(item) })
console.log(a2);
// 方法四
const a3 = []
a.sort()
a.forEach((item, index) => { a[index - 1] !== item && a3.push(item) })
console.log(a3)
// 方法五
// includes+findIndex
const a4 = []
a.forEach(item => { (a4.findIndex(item) === -1) && a4.push(item) })
console.log(a4)
12、数组扁平化
// 方法一
var a = [1, 2, [2, [1, 3, [7, 8]]]]
console.log(a.flat(Infinity));
// 方法二
function flatten1(arr) {
let res = []
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
res = res.concat(flatten1(arr[i]))
} else {
res.push(arr[i])
}
}
return res
}
console.log(flatten1(a));
// 方法三
function flatten2(arr) {
return arr.reduce((pre, cur) => { return pre.concat(Array.isArray(cur) ? flatten2(cur) : cur) }, [])
}
console.log(flatten2(a));
// 方法四
function flatten3(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr)
}
return arr
}
console.log(flatten3(a));
七、Map、Weakmap
map和object的区别,object只能使用字符串、数字、symbol作为key值;map可以使用任意类型作为key值;且map是有序的,object是无序的。
weakmap必须使用object作为key,weakmap中的weak表示key值的引用不算引用,对垃圾回收影响不大。
map有6个api:m.set()、m.has()、m.get()、m.size、m.delete()、m.clear()
map的迭代:
for(let pair of m.entries())、for(let key in of m.keys())、for(let key in of m.values())
八、Set、WeakSet
set有五个api:s.add()、s.has()、s.size()、s.delete()、s.clear()
weakset中的元素必须是object,或者继承object的类型。weakset中的weak表示value都是弱弱的引用,不会影响垃圾回收。