手写浅拷贝
浅拷贝一般在引用数据类型,复制后一个改变会影响另一个。
- 使用
Object.assign()
let a = [1,2,3]
let b = Object.assign(a) //[1,2,3]
a[0] = 8
a//[8,2,3]
b//[8,2,3]
- 使用ES6拓展的
...
注:ES6的...
扩展运算符只会浅拷贝第二层
let a = {age:18,
address:{
city:"sy"
}
}
let b = {...a}
a.age = 8
b.age //18
a.address.city = "dl"
b.address.city // "dl"
//若想不改变可以这样
let b = {...a,address:{...a.address}}
a.address.city = "dd"
b.address.city // dl
手写深拷贝
深拷贝于基本数据类型中,复制后互不影响
- 使用
JSON.parse(JSON.stringify())
let obj = {
a : 1,
b : {
x : 2
}
}
let b = JSON.parse(JSON.stringfy(obj ))
- 使用递归进行深拷贝
function deepClone(obj){
let res = obj instanceof Array ? [] : {}
for(let i in obj ){
if(obj.hasOwnPrototype(i)){
res[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i]
}
}
return res
}
手写Ajax
onreadyStatus
的状态码表示
onreadyStatus | 表示 |
---|---|
0 | 尚未初始化 |
1 | 调用open 方法 |
2 | 调用sned 方法,但无响应 |
3 | 开始接受响应数据 |
4 | 响应数据接受完毕 |
let xhr = null
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest()
}else{
xhr = new ActiveXObject('Microsoft.XMLHttp')
}
xhr.onreadyState = function(){
if(xhr.readyState === 4){
if(xhr.status>=200 && xhr.status < 300 || xhr.status ===304){
return xhr.responseText;
}else{
return xhr.status
}
}
}
xhr.open('get',"url",true)
xhr.sned(null)
- 基于
promise()
实现AJAX
function ajax(option,url,params){
return new Promise((resolved,rejected) =>{
let xhr
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest()
}else{
xhr = new ActiveXObject('Microsoft.XMLHttp')
}
xhr.onreadyState = function(){
if(xhr.readyState === 4){
if(xhr.status>=200&&xhr.status<300 || xhr.status===304){
resolved(xhr.responseText)
}else{
rejected(xhr.status)
}
}
}
if(option === "GET"){
xhr.open("get",url,true)
xhr.send(null)
}
else if(option === "POST"){
xhr.open("post",url,true)
shr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
xhr.send(JSON.stringify(params))
}
})
}
- 为什么不使用浏览器的
navigator.userAgent
?
该属性可伪造,且IE版本不兼容 - 为什么
open()
和send()
要放在onreadyStatusChange
事件后?
open()
和send()
会导致readyStatusChange
的变化。
为了兼容浏览器。
手写防抖
某一事件进行时,若再次执行事件将清空计时器,重新计时。
如:输入框频繁调用接口
function debounce(fn){
let timer = null
return function(){
if(timer) return
timer = setTimeout(() =>{
fn.apply(this,arguments)
timer = null
},2000)
}
}
手写节流
指定时间内事件只会执行一次
- 提交按钮
- 滚动条的位置
function throttle(fn,delay){
let prev = new Date()
return function(){
let now = new Date()
let that = this
let arg = arguments
if(now - prev >= delay){
fn.apply(that,arg)
prev = new Date()
}
}
}
setTimeout()
写法
function throttle(fn,delay){
let run = true
return function(){
if(!run) false
run = false
function setTimeout(() =>{
fn.apply(this,arguments)
run = true
},delay)
}
}
手写Promise()
class Promise(){
constructor(execuate){
this.status = "pending"
this.value = undefined
this.reason = undefined
let resolve = value =>{
if(this.status === "pending"){
this.status = "resolved"
this.value = value
}
}
let reject = reason =>{
if(this.status === "pending"){
this.status = "rejected"
this.reason = reason
}
}
try{
execuate(resolve,reject)
}catch(e){
reject(e)
}
then(onFulfilled, onRejected) {
switch (this.state) {
case 'fulfilled':
onFulfilled(this.value)
break
case 'rejected':
onRejected(this.value)
break
default:
}
}
}