每日手写js

1.手写一个简单渲染器,将虚拟dom渲染为真实dom

const vnode = {
  tag: 'div',
  props: {
    onclick: () => alert('hello')
  },
  children: 'click me'
}

// 手写一个渲染器,用来渲染上面的代码,把上面的代码渲染为真实dom
function renderer(vnode, container) {
  // 使用vnode.tag作为标签名创建DOM元素
  const el = document.createElement(vnode.tag)
  // 遍历vnode.props属性,将属性和事件添加到dom元素中
  for (const key in vnode.props) {
    // 如果开头以on结尾的key,说明是事件
    if (/^on/.test(key)) {
      el.addEventListener(
        // 
        key.substr(2).toLowerCase(), // 事件名称 onClick ---> click
        vnode.props[key] // 事件处理函数
      )
    }
  }
  if (typeof vnode.children === 'string'){
    // 如果是字符串,说明它是元素的文本子节点
    el.appendChild(document.createTextNode(vnode.children))
  }else if(Array.isArray(vnode.children)){
    vnode.children.forEach(v=>render(v,el))
  }
  container.appendChild(el)
}
// body作为挂载点
renderer(vnode,document.body)

2.手写ajax

// 手写ajax
const SERVER_URL = "/server"
let xhr = new XMLHttpRequest();
// 创建http请求  参数(请求的方法,请求的地址,是否异步和用户的认证信息)
xhr.open("GET",SERVER_URL, true);
// 设置状态监听函数
xhr.onreadystatechange = function(){
  if(this.readyState !== 4 ) return;
  // 当请求成功时
  if(this.status === 200){
    handle(this.response)
  }else{
    console.log(this.statusText);
  }
};
// 设置请求失败时的监听函数
xhr.onerror = function(){
  console.log(this.statusText);
}
// 设置请求投信息
xhr.responseType = "json";
xhr.setRequestHeader("Accept","application/json")
// 发送http请求
xhr.send(null)

3.用promise二次封装ajax

function getJSON(url){
  // 创建一个promise对象
  let promise = new Promise((res,rej)=>{
    let xhr = new XMLHttpRequest()
    // 创建一个http请求
    xhr.open("GET",url,true)
    xhr.onreadystatechange=function(){
      if(this.readyState !== 4) return;
      // 当请求成功或者失败时,改变promise状态
      if(this.status === 200 ){
        res(this.response)
      }else{
        rej(new Error(this.statusText));
      }
    };
    // 设置错误监听函数
    xhr.onerror = function(){
      rej(new Error(this.statusText))
    };
    // 设置请求头信息
    XMLHttpRequest.setRequestHeader("Accept","application/json");
    // 发送http请求
    xhr.send(null);
  });
  return promise
}

4.实现浅拷贝

  • **浅拷贝:**浅拷贝是将一个对象的属性复制到另一个值中,如果对象中属性的值为引用类型的时候,把这个引用类型的地址复制给对象。
  • **深拷贝:**深拷贝是将一个对象的属性复制到另一个值中,如果对象中属性的值为引用类型的时候,新建一个引用类型然后将对象中的值复制给他,而不是复制原来值得地址。
(1)、Object.assign(target,source…)
let a = {a:1}
let b = {b:2}
let c = {c:3}
let d = Object.assign(a,b,c)
console.log(a); // { a: 1, b: 2, c: 3 }
console.log(d); // { a: 1, b: 2, c: 3 }
(2)、扩展运算符
let obj1 = {a:1,c:{b:1}}
let obj2 = {...obj1}
console.log(obj1); // { a: 1, c: { b: 1 } }
console.log(obj2); // { a: 1, c: { b: 1 } }
obj1.a = 2
console.log(obj1); // { a: 2, c: { b: 1 } }
console.log(obj2); // { a: 1, c: { b: 1 } }
obj1.c.b = 2
console.log(obj1); // { a: 2, c: { b: 2 } }
console.log(obj2); // { a: 1, c: { b: 2 } }
(3)、Array.prototype.splice()
let arr1 = [1,2,3]
let arr2 = arr1.slice()
console.log(arr1); // [1,2,3]
console.log(arr2); // [1,2,3]
(4)、手写浅拷贝
// 浅拷贝的实现;

function shallowCopy(object) {
  // 只拷贝对象
  if (!object || typeof object !== "object") return;

  // 根据 object 的类型判断是新建一个数组还是对象
  let newObject = Array.isArray(object) ? [] : {};

  // 遍历 object,并且判断是 object 的属性才拷贝
  for (let key in object) {
    if (object.hasOwnProperty(key)) {
      newObject[key] = object[key];
    }
  }

  return newObject;
}

5.实现深拷贝

(1)、JSON.parse(JSON.stringify())
let a = {a:1,b:{c:1}}
let b = JSON.parse(JSON.stringify(a))
a.b.c= 2
console.log(a); // { a: 1, b: { c: 2 } }
console.log(b); // { a: 1, b: { c: 1 } }
(2)、lodash
let _ = require('lodash')
let a = { a: 1, b: { c: 2 } }
let b = _.cloneDeep(a)
a.b.c=3
console.log(a); // { a: 1, b: { c: 3 } }
console.log(b); // { a: 1, b: { c: 2 } }
(3)、手写深拷贝
function deepCopy(object){
  if(!object || typeof object !== "object") return ;
  let newObj = Array.isArray(object)?[]:{}
  for (const key in object) {
    if(object.hasOwnProperty(key)){
      newObj[key] = typeof object[key] === "object"?deepCopy(object[key]):object[key]
    }
      
  }
  return newObj
}

6.单例模式

实现Storage,使得该对象为单例,基于 localStorage 进行封装。实现方法 setItem(key,value) 和 getItem(key)。

class Storage {
  static getInstance(){
    // 判断是否 new 过一个实例
    if(!Storage.instance){
      Storage.instance = new Storage()
    }
    return Storage.instance
  }
  setItem(key,value){
    return localStorage.setItem(key,value)
  }
  getItem(key){
    return localStorage.getItem(key,value)
  }
}
const Storage1 = new Storage.getInstance()
const Storage2 = new Storage.getInstance()
Storage1.setItem('name','王杰')
Storage1.getItem('name')
Storage2.getItem('name')

// 返回true
Storage1 === Storage2

7.列表转树

// 列转树算法
transTree(data) {
  let result = []
  let map = {}
  if (!Array.isArray(data)) {//验证data是不是数组类型
     return []
  }
  data.forEach(item => {//建立每个数组元素id和该对象的关系
    map[item.ttId] = item //这里可以理解为浅拷贝,共享引用
  })
  data.forEach(item => {
    let parent = map[item.parentTtId] //找到data中每一项item的爸爸
    if (parent) {//说明元素有爸爸,把元素放在爸爸的children下面
       (parent.children || (parent.children = [])).push(item)
    } else {//说明元素没有爸爸,是根节点,把节点push到最终结果中
       result.push(item) //item是对象的引用
    }
  })
  return result //数组里的对象和data是共享的
},
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dnhz-w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值