前端实习准备 — JS大总结

56 阅读13分钟

一些小点

1.基本数据类型:String  Number  Boolean  Undefine  Null  Symbol  BigInt
2. 引用数据类型:Object  Funtion  Array 
3. 定义变量的方式 let  const  var
4. toString()返回对象类型的字符串表示,valueOf()返回对象本身

创建对象的方式

1. 普通模式
let p = {
name: "muggle",
call: function(){
    cnosole.log(this.name)
}
}

2. new模式
let p = new Object()
p.name = "muggle"
p.call = function(){}

3. 工厂模式
Function Person(){
    return {
        name:""muggle",
        call(){}
    }
}
let p = Person()

4. 构造函数模式
Function Person(){
    this.name = name;
    this.call = function(){};
}
let p = new Person()

5. class模式
Class Person{
    construtor(name){
        this.name = name;
    }
    call(){}
}
let p = new Person()

6. Oject.create()
let Person = {}
let p = Object.create(Person);

内置对象(三个方面:使用方式,属性,方法)

1. String
let str = ""
let str = new String("") 
let str = `hello,${name}!`// 模板字符串

str.length

str.toUpperCase()
str.toLowerCase()
str.slice(start,end) // 返回字符串
str.trim() // 去掉空白
str.replace(searchValue,newValue) // 替换首次匹配到的字符串
str.replaceAll(searchValue,newValue) // 替换所有字符串
str.split(separator) // 指定分隔符拆分字符串,返回数组
str.concat(str1,str2...) //连接多个字符串,返回字符串
str.repeat(count) // 重复字符串


2. Number
let n = 1
let n = new Number() 

Number.MAX_VALUE
Number.MIN_VALUE // 最小正数
Number.POSITIVE_INFINITY //正无穷
Number.NEGATIVE_INFINITY //负无穷

Number.isFinite(n)
Number.isInteger(n)
Number.isNaN(n)
Number.parseFloat(str)
Number.ParseInt(str)


3. Boolean
let isTrue = new Boolean(x) 


4.Symbol
let sym = Symbol("key") // 作为对象属性中的键(唯一)
let obj = {
    [sym]:"muggle"
}

Symbol.for("key") // 全局注册/查找symbol
Symbol.KeyFor("key") // 全局查找symbol

不能用于普通对象的for循环遍历


5. BigInt
let n = BigInt()


6. Array
let arr = []
let arr = new Array()

arr.length

Array.from() // 将其他数据类型(可迭代对象)转化为数组
Array.of(a,b,c) // 创建数组
Array.isArray()
// 改变自身
arr.push(value) // 添加末尾元素
arr.pop() // 删除末尾元素
arr.unshift(value) // 添加开头元素
arr.shift() // 删除开头元素
arr.splice(start,count) // 删除特定元素
arr.splice(start,count,value) // 插入元素
arr.splice(2,0,3,4) // 索引2处插入3和4,删除0个元素

// 不改变自身,返回新数组
arr.concat(arr1) // 合并数组
arr.slice(start,stop) // 截取数组,不包括stop
arr.join(separator) // 将数组的元素连接成字符串

// 不改变自身,遍历数组,针对每个元素使用回调函数
arr.forEach((item,index) => console.log(item,index)) // 单纯遍历一遍数组元素,不返回数组
arr.map((item) => item * 2) // 对每个元素处理,并返回处理过后的数组
arr.filter((item) => item %2 ===0) // 返回符合条件的数组
arr.find((item) => item>2 ) //返回符合条件的第一个元素
arr.findIndex((intem) => item>2) //返回符合条件的第一个元素的索引

// 改变自身,数组排序
arr.sort((a,b) => a-b) // 升序(比较函数,同时也是回调函数)
arr.sort((a,b) => b-a) // 降序
arr.sort() // 字符串数组排序
arr.reverse() // 反转数组


7. Set(WeakSet)
let set = new Set(arr) //自动去重,set为对象{}

set.size

set.add(a).add(b).add(c) // 添加元素,链式操作
set.delete(value) // 删除某个元素
set.has(value) // 是否存在某个值
set.keys() // 返回键 , 这三个方法,键值都一样
set.values() // 返回值
set.entries() // 返回键值对
set.clear() //清空集合
set.forEach((value) => console.log(value)) // 遍历集合

WeakSet只能存储对象、不支持遍历,未引用的对象会被垃圾回收


8. Map(WeakMap)
let map = new Map(['a', 1] , ['b', 2] ) // 键值对

map.size //键值对的数量 (键不能重复,值可以)

map.set(key,value) // 添加元素
map.get(key) // 输出value
map.delete(key) // 删除元素
map.has(key) // 判断是否有指定的键
map.keys()
map.values()
map.entries()
map.forEach((v,k) = > console.log(k , v)) // 先传v再传k的


9. Date
let date = new Date()

date.getFullYear()
date.getMonth()
date.getDate()
date.getDay()
date.getHour()
date.getMintes()
date.getSeconds()
date.getTime() // 时间戳(毫秒数),用于比较两个日期大小

date.toString()
date.toDateSrting()
date.toTimeString()


10. Math
直接调用,不需要实例化
Math.PI
Math.E
Math.ln2

Math.abs(x) // 绝对值
Math.ceil(x) // 向上取整
Math.floor(x) // 向下取整
Math.round(x) // 四舍五入
Math.max(x,y,z)
Math.min(x,y,z)
Math.pow(x,y) // x的y次方
Math.quart(x) // x的平方根
Math.sin(x)/cos(x)/tan(x) // x为角度
Math.log(x) // lnx
Math.log10(x) // log10x
Math.random() // 返回[0,1)之间的随机数,若想其他的可倍数


11. RegExp()
let regex = /abc/
let regex = new RegExp("模式""标志")
regex.test(str) // 是否符合正则表达式
// 模式
/abc/
.  \d  \D(数字)  \w  \W(字母) \s  \S(空白)
^开始 $结束  []集合 [^]集合取反
// 标志
g全局匹配  i忽略大小写

               
12. Error
let error = new Error("something wrong!")

error.message
error.name
error.stack // 错误位置,哪一行

throw new Error("error") // 抛出错误对象语句


13. JSON
const jsonString = {
    "name":"muggle",
    "age":23,
    "course": ["a","b","c"]
}
JSON.parse(jsonString) // JSON字符串转换为对象
JSON.stringify(obj)// 对象转换为JSON字符串


14. console
console.log()
console.info()
console.warn()
console.error()
console.assert()
console.table(obj/arr)

15. Function
function Fn(){} // 函数声明
let Fn = function(){} // 函数表达式
let f= new Fn(); // 构造函数
let f= (a) => "hello" + a  // 箭头函数

Fn.length // 返回函数参数的个数
Fn.constructor // 返回函数的构造函数 Function

// 用于更改函数的this指向,若this设为null,就是保持不更改(函数的this指向全局对象)
Fn.apply(thisArg, [a,b,c]) // Fn.apply(f)
Fn.call(thisArg, a, b, c)
Fn.bind(thisArg, a, b, c) // 返回新函数


16. Object
// 静态方法
Object.create(Person)
Object.assign(target, ...sources) // 将其他对象的属性复制到目标对象中
Object.keys(obj) // 返回所有可枚举属性的键(数组)
Object.values(obj) // 返回所有可枚举属性的值(数组)
Object.entries(obj) // 返回键值对(二维数组)
Object.getPrototypeof(obj) // 返回对象的原型
Object.setPrototypeOf(obj,obj_prototype) // 更改obj的原型为obj_prototype
// 实例方法
obj.hasOwnProperty(key) // 检查是否含有某属性
obj.isPrototypeOf(otherObj) // 检查是否是另一个对象的原型

判断类型的方式

1. typeof
`typeof` 操作符可以用来判断原始类型(如 `string``number``boolean``undefined`)和对象类型(如 `object``function`),数组是一个特殊的对象,null也被判定为对象(历史遗留)

2. instanceof
arr instanceof Array // true, 只能用于对象和类构造函数的实例判断

3. Object.prototype.toString.call() // 几乎能判断所有类型

in操作符和for

1. in 操作符
(1) key in Object  
key字符串或Symbol,表示检查的键(obj的键为属性,arr的键为索引)
Object是对象或数组
in检查对象自身和原型链,Object.hasOwmProperty只检查自身
返回true/false

(2) key in obj
const obj = {name:'muggle', age:23}
console.log("name" in obj) // true

(3) key in arr
const arr = [3,4,5]
console.log(0 in arr) //true
console.log(5 in arr) //false

2. for
(1) forEach((value,key)=>{} 遍历arr,map,set的键和值,不能遍历对象
arr.forEach
map.forEach
set.forEach // 无键2for(let key in obj){} 遍历对象的键(obj的属性,arr的索引)
for(let key in obj){
  console.log(key,obj.key)
}
for(let key in arr){
  console.log(key) // "0"  "1"  "3" // 返回的是索引的字符串
}

(3)for(let value of obj){} 遍历可迭代器的值(obj,arr,map,set,string)
for(let value of arr){
    console.log(value) // 3 4 5
}
// 解构赋值
const map = new Map([{name:'muggle'},{age:23}])
for (let {key,value} in map){  // {key,value}=v
    console.log()
}

数组去重、数组排序

1. 数组去重
let uniqueArr= new Set(arr)

2. 数组排序
arr.sort((a,b) => a-b) // 升序
arr.sort((a,b) => b-a) //降序

继承(本质要实现子类继承父类的属性和方法)

1. 原型链继承
// 将子类的原型设为父类的实例,并修正construtor的指向
Child.prototype = new Parent()
Child.prototype.constructor = Child
// 共享父类的属性,容易引发数据污染,无法初始化父类实例属性

2. 构造函数继承
// 子类构造函数中调用父类,让父类的属性直接复制到子类上
Parent.call(this, a, b, c)
// 无法继承父类方法

3. 组合继承
// 两者相加
Parent.call(this, a, b, c)
Child.prototype = new Parent()
Child.prototype.constructor = Child
// 可继承父类的属性和方法,每个实例的引用属性独立

4. class继承
// 在子类的constructor中使用super()声明和传参
class parent {
  constructor(name, age) {
      this.name = name;
      this.age = age;
  }
    getName() {
        console.log(this.name);
    }
}

class child extends parent{
    constructor(name, age, school) {
        super(name, age);
        this.school = school;
    }
    getSchool() {
        console.log(this.school);
    }
}

let c = new child('zhangsan', 18, 'beijing');
c.name = 'lisi';
c.school = 'shanghai';
c.getName();
c.getSchool();



解构赋值(前面解构=后面完整)和rest(...arg)

解构赋值:将数组或对象的值提取到变量中
1. 解构数组
const arr = [1,2,3]
const [A,B,C] = arr
console.log(A) // 1

2. 解构对象
const obj = {name:'muggle' , age:23}
const {name,age} = obj
const {name:username , age:userage} = obj //重命名变量
console.log(name) // muggle
console.log(username) // muggle

3. 嵌套解构
const obj ={name:'muggle' info:{age:23,addr:'NY'}}
const {info:{age,addr}} = obj
cosole.log(age) // 23

4. 解构用于函数传参
想象成赋值,形参 = 实参
function person({name,age}){
    console.log(name,age)
}
person({name:'muggle',age:23})

Rest参数:将多个剩余的值收集到一个数组或对象中
1. 数组rest
const arr = [1,2,3,4,5]
const [A,B,...C] = arr // rest用于解构赋值
console.log(C) // [3,4,5]

2. 对象rest
const obj = {name:'muggle',age:23,addr:'NY'}
const {name,...info} = obj
console.log(info) // {age:23,addr:'NY'}

3. 函数传参
function num(...numbers){
    numbers.forEach(value=>console.log(value))
}
num(1,2,3) // 关键点,值收集到数组/对象

浏览器特有的全局对象(属性、方法)

1. Window
最顶层的全局对象,其属性和方法可以直接调用(BOM)
// 属性
document
innerWidth\innerHeight
localStorage\sessionStorage
location
navigaror
screen
// 方法
alert("")
prompt(message,defaultValue)
setTimeout(callback,delay) // 延迟执行某函数
setInterval(callback,interval) // 固定时间间隔执行某函数
open(url,target) // 打开一个新窗口
scrollTo(x,y) // 滚动到指定位置


2. document
HTML文档,访问和操作页面内容(DOM)
// 属性
document.body // <body>
document.head
document.title
document.forms // 文档中所有<form>集合
document.images // 文档中所有<img>集合
// 方法
<div id='myDiv' class='highlight'>hello</div>
document.getElementById(id) // 通过ID获取元素
document.getElementsByClassName(classname) // 通过类名获取元素集合
selector = #id  .class  tagName  tagName[attribute] 
document.querySelector(selector) // 返回匹配选择器的第一个元素
document.querySelectorAll(selector) // 返回所有元素集合
document.createElement(tagName) // 自定义标签
document.parent.appendClild(node) // 向指定父节点添加子节点


3. Navigator(浏览器相关信息)
// 属性
navigator.userAgent // 浏览器信息
navigator.language // 当前语言
navigator.online // 是否联网
navigator.platform // 用户操作系统信息
// 方法
navigator.geolocation.getCurrentPositon(successCallback,errorCallback) // 获取当前位置
navigator.share(data) // 调用浏览器的共享功能


4. location(当前页面的URL// 属性
location.href // 完整URL
location.protocol // 协议 http:
location.hostname // 主机名 www.muggle.com
location.pastname // 路径 /about
location.search // 查询字符串 ?id=123
// 方法
location.assign(url) // 加载新页面
location.reload() // 重载当前页面
location,replace(url) // 替换当前页面


5. history (浏览器会话历史)
// 属性
history.length // 会话历史数量
// 方法
history.back() // 后退一页
history.forward() // 前进一页
history.go(delta) // 指定步数跳转
history.pushState(state,title,url) // 添加新状态
history.relaceState(state.title.url) //替换当前状态

事件

0. 对一个标签进行操作
const btn = document.getElementById("myButton");
btn.addEventListener("click",function(){})

1. 事件对象EventTarget
HTML元素、文档、窗口等都接入了EventTarget接口,都可以使用event的属性和方法
// 属性
event.type // 事件类型
event.target // 事件元素
event.bubbles // 事件是否会冒泡
// 方法
event.preventDefault() // 阻止事件默认行为
event.stopPropagation() // 阻止事件传播,防止事件冒泡/捕获
btn.addEventListener("click",function(event){
    event.stopPropagation();
})

2. 常用事件类型type
// 用户输入
click
dblclick
keydown 按下
keyup 松开
keypress a
input
change // 表单元素发生变化时

// 鼠标事件
mouseenter
mouseleave
mouseover // 冒泡
mouseout // 冒泡

// 表单事件
submit
focus // 表单元素获得焦点
blur // 失去焦点

// 窗口事件
load // 页面或图像完全加载时触发
resize // 窗口大小调整时触发
scroll //页面滚动时触发

// 其他
contextmenu // 右键触发
drag // 拖动元素触发
drop // 方向元素触发
focusin // 元素聚焦触发,冒泡
focusout // 元素失去焦点触发,冒泡


3. 事件监听与绑定
(1) 通过HTML属性绑定
<button id="myButton" onclick="alert("")"></button>

(2) 通过JS绑定
const btn = document.getElementById("myButton");
btn.addEventListener("click"function(){
    alert("");
})

(3)常用监听绑定函数
btn.addEventListener(type,callback,options/useCapture) // 添加监听器
btn.removeEventListener(type,callback,options/useCapture) // 移除监听器
btn.dispatchEvent(type) // 手动触发绑定在btn的事件

useCapture:默认为false,即默认冒泡触发)
options:capture(true,捕获时触发函数)  once(true,只触发一次函数)  passive(true,禁止调用preventDefault())  signal


4. 事件传播
(1)捕获阶段(window - document - 最外层父元素 - 目标元素)
设置btn.addEventListener(event,callback,true)触发,第三个元素默认为false,即默认事件在冒泡阶段触发

(2)目标阶段(事件到达目标元素,触发事件处理器)

(3)冒泡阶段(目标元素 - 最外层父元素 - document - window)
例如,当用户点击一个按钮时,事件首先在按钮上触发,然后冒泡到它的父元素、祖先元素,直到到达 document 元素。

// 阻止事件传播(冒泡)
btn.addEventListener("click" , function(event){
    event.stopPropagation();
})


5. 事件委托
(1)基于事件冒泡,原理是将事件监听器绑定到父元素上,这样子元素的处理事件可以通过事件冒泡机制由父元素捕获处理。
(2)优化性能,假设有成千上百个按钮,逐个绑定事件监听器会消耗大量内存,如ul和li就可以使用事件委托。
(3)动态添加元素,事件监听器被绑定到父元素上,可以随意添加子元素,后续都能触发事件。

操作DOM元素

除了上述获取元素+给元素绑定监听器+触发事件操作DOM元素外,还有一些常用属性和方法
document.getElementById('id').textContent // 标签内的文本内容
document.getElementById('id').innerText // 可见文本内容(包括可能因为CSS隐藏掉的)
document.getElementById('id').innerHTML //获取或插入HTML标签
document.getElementById('id').outerHTML  // 区别,这个包括元素本身
document.getElementById('id').value // 一般是表单元素的值
document.getElementById('id').style.color // 获取内联样式
document.getElementById('id').classList.add('active') // 获取元素的class属性,并提供了一些方法add(), remove(), toggle(), contains()
document.getElementById('id').getAtrribute('id') // 获取元素属性
document.getElementById('id').setAtrribute('class','myClass') // 添加元素属性
document.getElementById('id').hasAtrribute('href') // 检查元素是否有该属性
document.getElementById('id').focus() // 设置焦点,常用于表单元素

setTimeout和setInterval(两者用法一致)

setTimeout 延迟xx毫秒后执行回调函数
setInterval 间隔xx毫秒重复执行一次回调函数
// 返回一个timeId,可传参,时间单位为ms
const timeId = setTimeout(function(a, b){} , 2000 , a , b)
// 清除定时器
clearTimeout(timeId)

try...catch

用于捕获错误
try{
    // 放置可能抛出异常的代码
}catch(error){
    // try中抛出异常时执行
}

promise

1. Promise有三种状态:pendding  fulfilled  rejected

2. Promise对象是一个构造函数,用来生成Promise实例。接收一个函数作为参数,而这个函数的参数为resolve和reject函数,resolve将pendiing变为fulfilled,可以传入一个成功值给resolve,表示异步操作成功;reject将pendding变为rejected,可以传入一个失败值给reject,表示异步操作失败。
const promise = new Promise((resolve,reject) =>{
    if(异步操作成功){
        return resolve(value)
    }else{
        return reject(error)
    }
})
关于传入resolve和reject的值的类型,可以是字符串,也可以是其他类型,reject通常传入一个error对象的实例,resolve也可以传入一个promise
一般调用完resolve和reject之后promise的任务就完成了,确保不会再执行下面的语句,最好给其加上return3. Promise.prototpe.then()
接收两个回调函数作为参数,第一个回调是上一个promise对象状态为resolved时调用,第二个回调是上一个promise对象为rejected时调用,两个回调都接收上一个promise中传入resolve/reject函数的值作为参数。两个回调不一定都要提供。
then两个回调中的return值,就作为下一个then的传入值
promise.then(value=>{
    console.log(value)
    return "then.value"
},error=>{
    console.log(error)
    return "then.error"
})

4. Promise.prototype.catch() == .then(null,rejection)
用于捕获Promise对象reject返回的值,相当于then的第二个操作
catch能捕获promise的错误也能捕获then的错误。promise的错误有冒泡性质,会一直向后传递,直至被捕获。一般不用then的第二个参数,用catch代替
// 若promise没有抛出错误,会跳过catch
promise.then(value=>{
    console.log(value)
    return "then.value
}).catch(error=>{
    console.log(error)
    return "catch.error"
})

5. Promise.prototype.finally()  
无论成功失败在Promise执行结束后执行,做一些清理工作
promise.then(value=>{}).catch(error=>{}).finally(()=>{})

6. 抛出3种错误写法
const promise = new Promise((resolve,reject)=>{
    throw new Error('error')
})

// try...catch也主要用于捕捉同步错误
const promise = new Promise((resolve,reject)=>{
    try{
        throw new Error('error')
    }catch(e){
        reject(e)
    }
})

const promise = new Promise((resolve,reject)=>{
    reject(new Error('error'))
})

promise.catch((error)=>{
    console.log(error) // Error:error
})

7. Promise.all
接收一个数组/Iterator接口的,用于将多个promise实例,包装成一个新的promise
const p = Promise.all([p1,p2,p3])
当p1,p2,p3都为fulfilled时,p才为fulfilled
当有一个为rejected时,p就为rejected
const p1 = new Promise((resolve,reject)=>{
    resolve('success')
}).then(value=>{
    console.log(value)
}).catch(error=>{
    console.log(error)
})
const p2 = new Promise((resolve,reject)=>{
    reject('error')
}).then(value=>{
    console.log(value)
}).catch.(error=>{
    console.log(error)
})
Promise.all([p1,p2]).then((value=>{
    console.log(value) // ["success","error"]
})).catch(error=>{
    console.log(error) // 并不会捕获p2的错误,因为p2自身有catch已捕获错误并返回一个成功的promise。若p2没有catch,promise.all就变成调用reject(), 则会触发promise.all.catch,输出就为单独的error
})

8. Promise.resolve()
Promise.resolve('success') 等价于
new Promise((resolve)=>{
    resolve('success')
})

9. Prmosie.reject()
Promise.reject('error') 等价于
new Promise((reject)=>{
    reject('error')
})

aysnc...await (基于promise)

1. aysnc 定义异步函数的方式
// 函数声明
async function foo(){}
// 函数表达式
async foo = function(){}
// 箭头函数
const foo = async()=>{}
// 对象方法
const obj = {
    async foo(){}
} // obj.foo()
// 类方法
class Person{
    construtor(){}
    async foo(){}
}
const p = new Foo() // p.foo()

2. async...await
async: 定义一个异步函数,返回一个promise对象,return的值作为then的参数。顺序执行,遇到await停止,待await完成继续执行
await: 后面跟一个promise,返回promise的结果,如果没有跟promise就返回对应值,相当于return。所以await最好用一个try..catch包裹捕捉错误,不然await的promise出错会被async promise调用的catch捕捉,影响判断。只能用在async中。
async funtion foo(){
    try{
        await p1() // 先等待p1执行完,才执行p2
        await p2()
    }catch(error){
        console.log(error) // 如果p1出错,直接捕捉错误,不执行p2
    }
}
如果想要p1 p2同时触发(请求并发执行),使用promise.all

proxy

用于修改某些默认行为,在访问目标对象之前设一层拦截
proxy的构造和方法
let proxy = new Proxy(obj,{
    get:(obj,key)=>{},  // key为属性名
    set:(obj,key,value)=>{},  // value为要赋的值
    apply:(obj,this,...arg)=>{}, // this为修改obj的this指向
    has:(obj,key)=>{}, // key为要查询的属性名
    ....
}) 

Class

module语法: import export 动态导入

早期模块加载:CommonJs,同步加载,单一导出,require()运行时加载
如今模块加载:ES Modules,可异步加载,多种导出,静态导入
​
1. 导出export
// export支持三种接口:函数,类,变量(let const var)
export const name = 'muggle'
export function add(a,b){
    return a+b
}
export {name,add} // import的时候就可以解构赋值// as重命名
export {name as studentName}
​
// 错误写法
const name = 'muggle'
export name  // 必须要有一个对象包裹2. 导入import
// 默认只读,不能修改
import {name,add} from './xxx.js'// as重命名
import {name as studentName} from './xxx.js'// 整体加载*
import * as student from './xxx.js'
student.name
student.add(1,2)
​
3. 默认导出export default
导入导出都不需要{},default就作为默认接口,所以export时不需要命名,import时可以任意命名,只能有一个default
const name = 'muggle'
export default name
export default function(a,b){
    return a+b
}
// 不需要{}
import add from './xxx.js'4. 动态导入import()
import('./xxx.js')
返回一个promise,可以按需加载,条件加载(放在if之后),动态url(使用模板字符串)
路由懒加载使用这种方式

this

闭包

正则表达式

同步异步中断

localstorage和sessionstorage

JSON.stringfy()将对象或值转化为字符串,常用于发送
JSON.parse()将JSON字符串解析为对象
两者用法一样,不同的是localStorage是持久性存储,需要手动清除,同一域下所有标签页共享数据。sessionStorage仅在当前标签页有效。
// 存储数据
localStorage.setItem('itemName',JSON.stringfy(itemValue))
// 获取数据
JSON.parse(localStorage.getItem('itemName'))
// 删除数据
localStorage.removeItem('itemName')
// 清空所有数据
localStorage.clear()