JavaScript基础知识(一)
JavaScript基础知识(一)
1. 数据类型&判断
1.1. 数据类型
- Number
- String
- Boolean
- Undefined
- Null
- Symbol
- BigInt
- Object
1.2. 类型判断
typeof
1
2
3
4
5
6
7
8
9
10
11
12
13typeof 123 //number
typeof true //boolean
typeof "abc" //string
typeof undefined //undefined
typeof null //object
typeof 123n //bigint
typeof Symbol(a) //symbol
typeof [] //object
typeof {} //object
typeof function () {} //function
typeof NaN //number
typeof new Date() //object
typeof RegExp() //objectinstanceof
1
2
3
4function Person() {}
const p = new Person()
console.log(p instanceof Person) //true
console.log(p instanceof Object) //trueconstructor
1
2
3function Person() {}
const p = new Person()
console.log(p.constructor === Person) //trueArray
1
Array.isArray([]) //true
NaN
1
2
3isNaN(NaN) //true
isNaN(123) //false
isNaN("abc") //trueprototype
1
2
3
4
5
6
7
8
9
10
11
12Object.prototype.toString.call(123) //[object Number]
Object.prototype.toString.call("abc") //[object String]
Object.prototype.toString.call(true) //[object Boolean]
Object.prototype.toString.call(undefined) //[object Undefined]
Object.prototype.toString.call(null) //[object Null]
Object.prototype.toString.call(Symbol()) //[object Symbol]
Object.prototype.toString.call(123n) //[object BigInt]
Object.prototype.toString.call([]) //[object Array]
Object.prototype.toString.call({}) //[object Object]
Object.prototype.toString.call(function () {}) //[object Function]
Object.prototype.toString.call(new Date()) //[object Date]
Object.prototype.toString.call(RegExp()) //[object RegExp]
1.3. 判断是否相等
全等
1
2
3
4
5null == undefined //true
null === undefined //false
NaN == NaN //false
+0 === 0 //true
+0 === -0 //trueObject.is
1
2
3
4
5Object.is(null, undefined) //false
Object.is(NaN, NaN) //true
Object.is(+0, 0) //true
Object.is(-0, 0) //false
Object.is(+0, -0) //false
1.4. 判断是否为空
1 | //判断是否为null |
2. 构造函数&原型&实例&类
2.1. 关系
1 | //1.构造函数 |
2.2. 继承
2.2.1. 原型继承
1 | function SuperType(name,age){ |
2.2.2. 经典继承
1 | function SuperType(name,age){ |
2.2.3. 组合继承
1 | function SuperType(name,age){ |
2.2.4. 原型式继承
1 | function object(o){ |
2.2.5. 寄生式组合继承
1 | function object(o){ |
2.3. 类
2.3.1. 类的构成
1 | class Foo{ |
2.3.2. 类继承
1 | class Super{ |
3. 数组遍历
- for循环
1
2
3
4let arr = [2,3,5,7,11,13,17,19];
for(let i = 0, len = arr.length ; i < len ; i++ ){
console.log(arr[i]);
} - forEach
1
2
3
4let arr = [2,3,5,7,11,13,17,19];
arr.forEach(function(item,index,arr){
console.log(item)
}) - for…in
1
2
3
4let arr = [2,3,5,7,11,13,17,19];
for(let index in arr){
console.log(arr[index]);
} - for…of
1
2
3
4let arr = [2,3,5,7,11,13,17,19];
for(let item of arr){
console.log(item);
} - Object.entries
1
2
3
4let arr = [2,3,5,7,11,13,17,19];
for(let [index,item] of arr.entries()){
console.log(index,item);
} - Object.keys()
1
2
3
4let arr = [2,3,5,7,11,13,17,19];
for(let index of arr.keys()){
console.log(index);
} - Object.values()
1
2
3
4let arr = [2,3,5,7,11,13,17,19];
for(let item of arr.values()){
console.log(item);
}
4. 对象遍历
- for-in 循环——只遍历可枚举属性,包含实例属性和原型属性
1
2
3
4
5
6
7
8
9
10const obj = {
a:123,
b:'abc',
c:function(){
console.log()
}
}
for( let key in obj){
console.log(obj[key])
} - Object.keys()——只遍历可枚举属性,只包含实例属性
1
2
3
4
5
6
7
8
9const obj = {
a: 123,
b: "abc",
c: function () {
console.log()
}
}
const res = Object.keys(obj)
console.log(res) - Object.values()——只遍历可枚举属性,只包含实例属性
1
2
3
4
5
6
7
8
9const obj = {
a: 123,
b: "abc",
c: function () {
console.log()
}
}
const res = Object.values(obj)
console.log(res) - Object.entries()——只遍历可枚举属性,只包含实例属性
1
2
3
4
5
6
7
8
9const obj = {
a: 123,
b: "abc",
c: function () {
console.log()
}
}
const res = Object.entries(obj)
console.log(res) - Object.getOwnPropertyNames——遍历所有属性,除了Symbol属性,包含可枚举和不可枚举,包含实例属性和原型属性
1
2
3
4
5
6
7
8
9
10const obj = {
a: 123,
b: "abc",
c: function () {
console.log()
},
[Symbol()]:111
}
const res = Object.getOwnPropertyNames(obj)
console.log(res) - Object.getOwnPropertySymbols——只遍历Symbol属性,包含可枚举和不可枚举,包含实例属性和原型属性
1
2
3
4
5
6
7
8
9
10const obj = {
a: 123,
b: "abc",
c: function () {
console.log()
},
[Symbol()]:111
}
const res = Object.getOwnPropertySymbols(obj)
console.log(res) - Reflect.ownKeys——遍历所有属性,包含可枚举和不可枚举,包含实例属性和原型属性
1
2
3
4
5
6
7
8
9
10const obj = {
a: 123,
b: "abc",
c: function () {
console.log()
},
[Symbol()]:111
}
const res = Reflect.ownKeys(obj)
console.log(res)
5. 对象解构
1 | const obj = { |
6. 展开运算符
6.1. 展开数组
1 | //数组转换 |
6.2. 展开函数
1 | function f(...args) { |
6.3. 展开对象
对象浅拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21//对象浅拷贝
let obj1 = {
a: 1,
b: "xyz",
c: function () {},
d: {
m: 123
},
[Symbol()]: 1
}
let obj2 = { ...obj1 }
console.log(obj2) //{ a: 1, b: 'xyz', c: [Function: c], d: { m: 123 }, [Symbol()]: 1 }
obj2.a = 2
console.log(obj1) //{ a: 1, b: 'xyz', c: [Function: c], d: { m: 123 }, [Symbol()]: 1 }
console.log(obj2) //{ a: 2, b: 'xyz', c: [Function: c], d: { m: 123 }, [Symbol()]: 1 }
obj2.d.m = 456
console.log(obj1) //{ a: 1, b: 'xyz', c: [Function: c], d: { m: 456 }, [Symbol()]: 1 }
console.log(obj2) //{ a: 2, b: 'xyz', c: [Function: c], d: { m: 456 }, [Symbol()]: 1 }对象合并
1
2
3
4
5
6
7
8
9
10
11
12
13//合并对象
let obj1 = {
a: 1,
b: "xyz",
c: function () {},
d: {
m: 123
},
[Symbol()]: 1
}
let obj2 = { ...obj1, e: 111 }
console.log(obj2) //{ a: 1, b: 'xyz', c: [Function: c], d: { m: 123 }, e: 111, [Symbol()]: 1 }对象解构
1
2
3
4
5
6
7
8
9
10
11
12let obj1 = {
a: 1,
b: "xyz",
c: function () {},
d: {
m: 123
},
[Symbol()]: 1
}
let { a, b, ...obj2 } = obj1
console.log(obj2) //{ c: [Function: c], d: { m: 123 }, [Symbol()]: 1 }
7. Object 方法
Object.assign
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32//浅拷贝
const obj1 = {
a: 1,
b: "xyz",
c: function () {},
d: {
m: 123
}
}
const obj2 = Object.assign({},obj1)
console.log(obj2) //{ a: 1, b: 'xyz', c: [Function: c], d: { m: 123 } }
obj2.d.m = 456
console.log(obj1) //{ a: 1, b: 'xyz', c: [Function: c], d: { m: 456 } }
console.log(obj2) //{ a: 1, b: 'xyz', c: [Function: c], d: { m: 456 } }
//合并
const obj1 = {
a: 1,
b: "xyz",
c: function () {},
d: {
m: 123
}
}
const obj2 = {
a: 2,
b: "abc"
}
const obj3 = Object.assign(obj1, obj2)
console.log(obj3) //{ a: 2, b: 'abc', c: [Function: c], d: { m: 123 } }Object.create
1
2
3
4
5
6
7
8
9
10
11
12
13
14//创建新对象,源对象是新对象的原型
const obj1 = {
a: 1,
b: "xyz",
c: function () {},
d: {
m: 123
}
}
const obj2 = Object.create(obj1)
console.log(obj2.a) //1
obj2.d.m = 456
console.log(obj1) //{ a: 1, b: 'xyz', c: [Function: c], d: { m: 456 } }Object.defineProperty
1
2
3
4
5
6
7
8
9
10//对象添加属性
const obj = {}
Object.defineProperty(obj, "a", {
configurable: true,
enumerable: true,
writable: true,
value: 123
})
obj.a = 456
console.log(obj) //{a:456}Object.defineProperties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19//对象多个属性
const obj = {}
Object.defineProperties(obj, {
a: {
configurable: true,
enumerable: true,
writable: true,
value: 123
},
b: {
configurable: true,
enumerable: true,
writable: true,
value: {
m: 10
}
}
})
console.log(obj) //{ a: 123, b: { m: 10 } }Object.entries
1
2
3
4//返回对象可枚举属性的键值对数组
const obj = { a: 123, b: { m: 10 } }
const res = Object.entries(obj)
console.log(res) //[ [ 'a', 123 ], [ 'b', { m: 10 } ] ]Object.fromEntries
1
2
3
4//键值对列表转换为一个对象
const obj = { a: 123, b: { m: 10 } }
const res = Object.entries(obj)
console.log(res) //{ a: 123, b: { m: 10 } }Object.getOwnPropertyDescriptor
1
2
3
4//返回对象的某个元素的描述符
const obj = { a: 123, b: { m: 10 } }
const res = Object.getOwnPropertyDescriptor(obj, "a")
console.log(res) //{ value: 123, writable: true, enumerable: true, configurable: true }Object.getOwnPropertyDescriptors()
1
2
3
4//返回对象的所有自身属性的描述符
const obj = { a: 123, b: { m: 10 } }
const res = Object.getOwnPropertyDescriptors(obj)
console.log(res) //Object.getOwnPropertyNames
1
2
3
4//对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组
const obj = { a: 123, b: { m: 10 } }
const res = Object.getOwnPropertyNames(obj)
console.log(res) //[ 'a', 'b' ]Object.getOwnPropertySymbols
1
2
3
4//对象的所有自身属性的属性名(只包括 Symbol 值作为名称的属性)组成的数组
const obj = { a: 123, b: { m: 10 }, [Symbol()]: 1 }
const res = Object.getOwnPropertySymbols(obj)
console.log(res) //[ Symbol() ]Object.freeze
1
2
3
4
5//冻结一个对象,不能被修改
const obj = { a: 123, b: { m: 10 } }
Object.freeze(obj)
obj.a = 456
console.log(obj) //{ a: 123, b: { m: 10 } }Object.getPrototypeOf
1
2
3
4//对象的原型
const obj = { a: 123, b: { m: 10 } }
const res = Object.getOwnPropertyNames(obj)
console.log(res) //[Object: null prototype] {}Object.prototype.hasOwnProperty()
1
2
3
4//对象的是否有指定属性,不包含原型属性
const obj = { a: 123, b: { m: 10 } }
const res = obj.hasOwnProperty('a')
console.log(res) //trueObject.prototype.isPrototypeOf
1
2
3
4//对象是否存在于另一个对象的原型链上
const obj = { a: 123, b: { m: 10 } }
const res = obj.isPrototypeOf(Object)
console.log(res) //falseObject.is
1
2
3
4
5
6//判断两个值是否为同一个值
Object.is(null, undefined) //false
Object.is(NaN, NaN) //true
Object.is(+0, 0) //true
Object.is(-0, 0) //false
Object.is(+0, -0) //falseObject.keys
1
2
3
4//返回对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致
const obj = { a: 123, b: { m: 10 } }
const res = Object.keys(obj)
console.log(res) //[ 'a', 'b' ]Object.values
1
2
3
4//返回对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同
const obj = { a: 123, b: { m: 10 } }
const res = Object.keys(obj)
console.log(res) //[ 123, { m: 10 } ]
8. Array 方法
- Array.isArray —— 判断是否为数组
- Array.of ——参数变数组
1
Array.of(1,2,3) ;//[1, 2, 3]
- Array.from ——类似数组或可迭代对象创建一个新的,浅拷贝的数组实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16Array.from('foo') // ['f','o','o']
Array.from([1, 2, 3], x => x + x) //[2, 4, 6]
const set = new Set(['foo', 'bar', 'baz', 'foo'])
Array.from(set) //['foo', 'bar', 'baz']
const map = new Map([[1, 2], [2, 4], [4, 8]])
Array.from(map) //[[1, 2], [2, 4], [4, 8]]
const mapper = new Map([['1', 'a'], ['2', 'b']])
Array.from(mapper.values()) //['a', 'b']
Array.from(mapper.keys()) //['1', '2']
Array.from([1, 2, 3], x => x + x) //[2, 4, 6]
Array.from({ length: 3 }, (_, i) => i) // [0,1,2] 序列生成器 - concat ——合并两个或多个数组,不改变当前数组,返回新数组
- pop ——从数组中删除最后一个元素,并返回该元素的值。改变数组的长度
- push ——将一个或多个元素添加到数组的末尾,并返回该数组的新长度。改变数组的长度
- shift ——从数组中删除第一个元素,并返回该元素的值。改变数组的长度
- unshift ——将一个或多个元素添加到数组的开头,并返回该数组的新长度。改变数组的长度
- splice ——删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
- slice ——返回一个新的数组对象,由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。不改变当前数组
- every ——数组内的所有元素是否都能通过某个指定函数的测试。返回一个布尔值
- some ——数组内的至少有 1 个元素通过了被提供的函数测试。返回一个布尔值
- map ——创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成
- filter ——创建一个新数组,其包含通过所提供函数实现的测试的所有元素
- reduce ——迭代归并
- join ——一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串,可传参数
- sort ——元素进行排序。默认排序是将元素转换为字符串,比较它们的 UTF-16 代码,可传入自定义比较函数。改变原数组
- reverse ——元素的位置倒叙,改变原数组
- find ——返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined
- findIndex ——返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1
- indexOf ——返回在数组中可以找到一个给定元素的第一个索引。否则返回-1
- lastIndexOf ——返回在数组中可以找到一个给定元素的最后一个索引。否则返回-1
- includes ——判断一个数组是否包含一个指定的值,返回布尔值
- entries ——返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对
- values ——返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值
- keys ——返回一个包含数组中每个索引键的Array Iterator对象
- forEach ——对数组的每个元素执行一次给定的函数
- copyWithin ——浅复制数组的一部分到同一数组中的另一个位置,并返回它。不改变原数组
- toStrng —— 返回一个字符串,表示指定的数组及其元素
- fill ——用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引
- flat ——按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回
1
2
3
4
5
6
7const arr1 = [0, 1, 2, [3, 4]];
console.log(arr1.flat());
// expected output: [0, 1, 2, 3, 4]
const arr2 = [0, 1, 2, [[[3, 4]]]];
console.log(arr2.flat(2));
// expected output: [0, 1, 2, [3, 4]]
9. 数组去重
- 遍历循环判断
1
2
3
4
5
6
7
8
9
10
11function norepeat(arr) {
for (let i = 0, len = arr.length; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] === arr[j] || Object.is(arr[i], arr[j])) {
arr.splice(j, 1)
}
}
}
return arr
}
//无法去除[] {} function(){} - Set
1
[...new Set(arr)]
- indexOf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27function norepeat(arr) {
const newarr = []
arr.forEach(function (item) {
if (newarr.indexOf(item) === -1) {
newarr.push(item)
}
})
return newarr
}
function norepeat(arr) {
const newarr = []
arr.forEach(function (item,index) {
if (arr.indexOf(item) === index) {
newarr.push(item)
}
})
return newarr
}
function norepeat(arr) {
return arr.filter(function (item,index) {
return arr.indexOf(item) === index
})
}
//不能判断NaN - includes
1
2
3
4
5
6
7
8
9function norepeat(arr) {
const newarr = []
arr.forEach(function (item, index) {
if (!newarr.includes(item)) {
newarr.push(item)
}
})
return newarr
} - Map
1
2
3
4
5
6
7
8
9
10
11function norepeat(arr) {
const newarr = []
const map = new Map()
arr.forEach(function (item) {
if (!map.has(item)) {
newarr.push(item)
map.set(item, true)
}
})
return newarr
} - object
1
2
3
4
5
6
7
8
9
10
11function norepeat(arr) {
const newarr = []
const obj = {}
arr.forEach(function (item) {
if (!obj[item]) {
newarr.push(item)
obj[item] = true
}
})
return newarr
}
10. 多维数组遍历
1 | function flatten(sourceArr, flattenedArr = []) { |
11. 浅拷贝&深拷贝
11.1. 数组浅拷贝
- 展开运算符
1
2
3
4
5
6
7const a1 = [1, 2, 3, [6, 7]]
const a2 = [...a1]
a2[2] = 5
a2[3][1] = 8
console.log(a1) //[ 1, 2, 3, [ 6, 8 ] ]
console.log(a2) //[ 1, 2, 5, [ 6, 8 ] ] - Array.from
1
2
3
4
5
6
7const a1 = [1, 2, 3, [6, 7]]
const a2 = Array.from(a1)
a2[2] = 5
a2[3][1] = 8
console.log(a1) //[ 1, 2, 3, [ 6, 8 ] ]
console.log(a2) //[ 1, 2, 5, [ 6, 8 ] ] - slice
1
2
3
4
5
6
7const a1 = [1, 2, 3, [6, 7]]
const a2 = a1.slice()
a2[2] = 5
a2[3][1] = 8
console.log(a1) //[ 1, 2, 3, [ 6, 8 ] ]
console.log(a2) //[ 1, 2, 5, [ 6, 8 ] ] - concat
1
2
3
4
5
6
7const a1 = [1, 2, 3, [6, 7]]
const a2 = a1.concat([])
a2[2] = 5
a2[3][1] = 8
console.log(a1) //[ 1, 2, 3, [ 6, 8 ] ]
console.log(a2) //[ 1, 2, 5, [ 6, 8 ] ] - filer
1
2
3
4
5
6
7
8
9const a1 = [1, 2, 3, [6, 7]]
const a2 = a1.filter(function (item) {
return true
})
a2[2] = 5
a2[3][1] = 8
console.log(a1) //[ 1, 2, 3, [ 6, 8 ] ]
console.log(a2) //[ 1, 2, 5, [ 6, 8 ] ] - map
1
2
3
4
5
6
7
8
9const a1 = [1, 2, 3, [6, 7]]
const a2 = a1.map(function (item) {
return item
})
a2[2] = 5
a2[3][1] = 8
console.log(a1) //[ 1, 2, 3, [ 6, 8 ] ]
console.log(a2) //[ 1, 2, 5, [ 6, 8 ] ]
11.2. 数组深拷贝
- JSON 转换
1
2
3
4
5
6
7const a1 = [1, 2, 3, [6, 7]]
const a2 = JSON.parse(JSON.stringify(a1))
a2[2] = 5
a2[3][1] = 8
console.log(a1) //[ 1, 2, 3, [ 6, 7 ] ]
console.log(a2) //[ 1, 2, 5, [ 6, 8 ] ] - 自定义函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24function deepcloneObj(obj) {
const deepclonedobj = Array.isArray(obj) ? [] : {}
if (obj && typeof obj === "object") {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") {
deepclonedobj[key] = deepcloneObj(obj[key])
} else {
deepclonedobj[key] = obj[key]
}
}
}
}
return deepclonedobj
}
const a1 = [1, 2, 3, [6, 7]]
const a2 = deepcloneObj(a1)
a2[2] = 5
a2[3][1] = 8
console.log(a1) //[ 1, 2, 3, [ 6, 7 ] ]
console.log(a2) //[ 1, 2, 5, [ 6, 8 ] ]
11.2. 浅拷贝
- 展开运算符
1
2
3
4
5
6
7
8
9
10
11const obj1 = {
x: 123,
y: "abc",
z: {
a: 111
}
}
const obj2 = { ...obj1 }
obj2.x = 456
obj2.z.a = 222
console.log(obj1) //{ x: 123, y: 'abc', z: { a: 222 } } - Object.assign
1
2
3
4
5
6
7
8
9
10
11const obj1 = {
x: 123,
y: "abc",
z: {
a: 111
}
}
const obj2 = Object.assign({}, obj1)
obj2.x = 456
obj2.z.a = 222
console.log(obj1) //{ x: 123, y: 'abc', z: { a: 222 } } - 自定义函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31//简单深拷贝
function deepcloneObj1(obj) {
const deepclonedobj = Array.isArray(obj) ? [] : {}
if (obj && typeof obj === "object") {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") {
deepclonedobj[key] = deepcloneObj(obj[key])
} else {
deepclonedobj[key] = obj[key]
}
}
}
}
return deepclonedobj
}
const obj1 = {
x: 123,
y: "abc",
z: {
m: 111
}
}
const obj2 = deepcloneObj1(obj1)
obj2.z.m = 222
console.log(obj1) //{ x: 123, y: 'abc', z: { m: 111 } }
console.log(obj2) //{ x: 123, y: 'abc', z: { m: 222 } }
//进阶深拷贝
//.....- jQuery extends
- lodash _deepclone
12. 手写 Promise
13. fetch、 ajax
14. 防抖和节流
- 防抖 ——持续触发事件时,一定时间内没有去触发事件,事件才会执行一次;一定时间内触发事件,需要重新计时,直到满足指定时间再执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14function debounce(fn,wait){
let timer = null
return function(){
const that = this
const args = arguments
if(timer){
clearTimeout(timer)
}
timer = setTimeout(function(){
fn.apply(that,args)
}, wait)
}
} - 节流 ——持续触发事件时,在一定时间内只执行一次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function throttle(fn,wait){
let timer = null
const pre_time = new Date()
return function(){
const that = this
const args = arguments
const now_time = new Date()
if(now_time - pre_time >=wait){
fn.apply(that, args)
}
else {
if(!timer){
timer = setTimeout(function(){
fn.apply(that, args)
clearTimeout(timer)
},now_time - pre_time)
}
}
}
}
15. async 、await
15.1. 介绍
- async是函数声名的关键字
- await用在async函数内部
- async函数返回的是一个promise
- 优化处理promise
- 使用try…catch进行错误处理
15.2. 优点
- 代码清晰简洁
- 减少回调
16. apply、call、bind
- 相同点:
- 改变this指向,修改作用域
- 不同点:
- apply的第二个参数是数组,call是一个个的单独参数
- apply、call是立即执行函数,bind只是返回一个函数
17. 代理
18. Map、Set
18.1. 概念
- Map:键值对的数据映射集合
- Set:有序的数据集合列表,元素相互独立且唯一非重复
18.2. 用法
Map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49//新建
const map = new Map()
//或者
const map = new Map(['key1','value1'],['key2','value2'])
//或者
const map = new Map().set('key1','value1').set('key2','value2')
//长度
map.size
//增加元素
map.set('keya','valuea')
//获取
const val = map.get('keya')
//判断是否含有某元素
const res = map.has('keya')
//删除某元素
map.delete('keya')
//清空
map.clear()
//迭代
for(let m of map){
//按照之前插入map的顺序迭代
}
for(let m of map.entries()){
}
for(let m of map.keys()){
}
for(let m of map.values()){
}
for(let m of map[Symbol.iterator]()){
}
[...map]
map.forEach((value,key)=>{})Set
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45//新建
const set = new Set()
//或者
const set = new Set(['value1','value2'])
//或者
const set = new Set().add('value1').add('value2')
//长度
set.size
//增加元素
set.add('valuea')
//判断是否含有某元素
const res = set.has('valuea')
//删除某元素
set.delete('keya')
//清空
set.clear()
//迭代
for(let s of set){
//按照之前插入set的顺序迭代
}
for(let s of set.entries()){
}
for(let s of set.keys()){
}
for(let s of set.values()){
}
for(let s of set[Symbol.iterator]()){
}
[...set]
set.forEach((value,key)=>{})
18.3. WeakMap、WeakSet
- WeakMap ——弱映射,Map的健只能是Object或者继承于Object,不可迭代,不可clear
- WeakSet ——弱集合,元素只能是Object或者继承于Object,不可迭代,不可clear
19. 事件循环Event Loop
19.1. JS语言的特点
- 概念:单线程、非阻塞的脚本语言
20. this
- 确定过程:创建执行上下文时,创建变量对象、确定作用域链、确定this指向
- this指向是在函数被调用时确定的
- 全局this,一般指向window
- 函数中的this由调用者提供,指向由调用方式决定
- 如果调用者函数被某一对象所拥有,函数调用时,this指向该对象
- 如果函数独立,函数内部的this指向undefined,非严格模式下,this指向undefined时,会自动指向window
- call和aplly改变this的指向
- 构造函数中的this,指向新的实例对象
- 箭头函数没有this,到上级作用域找this,上级作用域没有this则继续往上找;箭头函数绑定apply、call、bind只传递参数,不绑定this
21. 作用域、作用域链、执行上下文、闭包
- 执行上下文 ——代码的执行环境
- 执行环境:全局环境、函数环境、eval
- 全局执行上下文在js代码开始运行时创建
- 函数的执行上下文在函数被调用时创建
- 作用域 ——变量和函数可以访问的范围
- 作用域链 ——变量的可访问作用域对象的集和
- 闭包 ——可访问另一个函数作用域的变量的函数,继续使用函数声名时的作用域,保护函数内部变量,回调函数
22. var 、let、const
- var、let ——定义变量
- const ——声名常量
- const必须初始化
- const不可修改,除了对象中的元素
- const、let不可重复定义
- const、let不是全局对象的属性
- 变量提升 ——let、const需要先声名再使用
- 块级作用域 ——if、while、for循环、switch、大括号、函数等
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 浮生二三四!