手写代码小记

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。

手写代码示例

实现Object.create

Object.create:创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。

const mycreate = function(obj){
    function F(){}
    F.prototype=obj
    return new F()
}
复制代码

原生实现jsonp

思路:<script>标签可以跨域引入资源,通过指定callback回调函数得到数据。

//原理:<script>标签可以跨域引入资源
var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'http://localhost:8080/users?username=xbc&callback='+callbackName;
    document.body.appendChild(script);
    // 回调执行函数
    function callbackName(res) {
        data = JSON.stringify(res)
        console.log(data);
    }
    ps:注意指定函数名callbackName
复制代码

原生实现http请求

思路:通过new XMLHttpRequest()实现,捕获onreadystatechange并做对应的处理。

重要:XMLHttpRequest

    const getJSON = function (url) {
		return new Promise((resolve, reject) => {
			const xhr = new XMLHttpRequest();
			// xhr.setRequestHeader("Content-Type", "application/json");
                        xhr.open("GET", url);
			xhr.onreadystatechange = function () {
				if (xhr.readyState !== 4) return;
                                // 状态码为200至300之间或304都表示这一请求已经成功
				if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
					resolve(xhr.responseText);
				} else {
					reject(new Error(xhr.responseText));
				}
			};
                        xhr.send(); //xhr.send(data) POST
		});
	};
        // 兼容IE5和IE6可选
	// function createXHR() {
	// 	if (window.XMLHttpRequest) {
	// 		return new XMLHttpRequest();
	// 	} else {
	// 		return new ActiveXObject('Microsoft.XMLHttp');
	// 	}
	// }
        ps:主要属性 on ready state change

复制代码

数组排序

1. 函数-sort

const arr=[1,30,4,21,99]
arr.sort((a,b)=>{
 return a - b;
})
//[1, 4, 21, 30, 99]
//ps: b - a; 大到小 
//sort函数还可以根据指定属性值排序json数组
例:
arr.sort((a,b)=>{
 return a.key - b.key
})

复制代码

2. 冒泡

思路:两两对比,反序则交换

//思路:两两对比,反序则交换
const arr=[1,20,4,21,99,88]
for(let i=0;i<arr.length-1;i++){
    for(let n=0;n<arr.length-i-1;n++){
        if(arr[n]>arr[n+1]){
            let x=arr[n]
            arr[n]=arr[n+1]
            arr[n+1]=x
        }
    }
}
//[1,4,21,30,88,99]
//ps:arr[n]<arr[n+1];大到小
复制代码

3. 快排

思路:先从数组中找一个基准数,把数组拆解成大于基准数区和小于基准数区两部分,再对左右区间重复第二步,直到各区间只有一个数

//思路:先从数组中找一个基准数,把数组拆解成大于基准数区和小于基准数区两部分,再对左右区间重复第二步,直到各区间只有一个数
const arr=[1,20,3,21,99,88]
function quick(arr){
    if(arr.length<=1) return arr;
    let left=[], right=[], mid=arr.splice(0,1)[0]
    for(let i=0;i<arr.length;i++){
        if(arr[i]<mid){
            left.push(arr[i])
        }else{
            right.push(arr[i])
        }
     }
     return quick(left).concat(mid,quick(right))
}
// [1, 3, 20, 21, 88, 99]
//ps:arr[i]>mid;大到小
复制代码

数组合并&去重

//2021年了,扩展运算符。(当然方法很多map、key值去重、过滤器等)
const a=[1,2,3]
const b=[4,5,6]
const c=[...new Set([...a,...b])];
//[a,b,c,d,e,f]

复制代码

非空判断不包含0

let value=0
if((value??'') !== ''){
    console.log('非空')
}
ps:这里对两个假值('' 或 0)做处理,当value为0时,结果就是(0!=='')得到true。  
    当value为''时,结果就是(''!=='')得到false。
复制代码

重点:空值合并操作符?? )是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。(另外??运算符和其他逻辑运算符之间的运算顺序目前没有明确说明,所以用())

拷贝

let obj={
    name:'张三',
    age:'18',
    grades:[88,99,58,68]
}
//浅拷贝
let obj2={...obj}
//深拷贝
let obj2=JSON.parse(JSON.stringify(obj));
//ps:根据实际场景来使用,复杂场景可以使用工具库,比如lodash
复制代码

原型链继承

思路:
1、让子类能访问父类的方法
2、对constructor处理,让子类的constructor属性指向自身(constructor属性是对函数本身的引用)

   // 父类方法(Superclass)
    function Superclass() {
        this.supName = "我是父类"
    }
    // 父类添加原型方法
    Superclass.prototype.showSupName = function () {
        console.log(this.supName)
    }
    //子类(Subclass)
    function Subclass() {
        this.subName = "我是子类"
    }
    /**
     * 1 让子类能访问父类的方法
     * 2 让子类的constructor属性指向自身(constructor属性是对函数本身的引用)
     **/
    Subclass.prototype = new Superclass();
    Subclass.prototype.constructor = Subclass
    // 子类添加原型方法
    Subclass.prototype.showSubName = function () {
        console.log(this.subName)
    }
    // 子类调用父类方法
    var sub = new Subclass();
    sub.showSupName();

  /*ps:如果想要继承父类的属性可调用父类的function.call(thisArg, arg1, arg2, ...);方法给父类提供子类的this值来实现*/
  
复制代码

Proxy使用,监听数据变化更新dom

思路:通过创建代理对象,对handler.set()设置属性值劫持,然后更新innerHTML

    <div id="name"></div>
    ---------------------------华丽的分割线----------------------------
    let data = {
        name: '唐三'
    }
    const handler = {
        set: function (obj, prop, val) {
            console.log(obj[prop], '监听set改变', obj, prop, val)
            obj[prop] = val;
            observer();
        }
    };
    const p = new Proxy(data, handler);
    document.getElementById('name').innerHTML = p.name
    //打怪升级
    setTimeout(() => {
        p.name = '海神'
    }, 2000);
    function observer() {
        document.getElementById('name').innerHTML = p.name
    }


ps:**Proxy** 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)
复制代码

note:handler对象如果没有定义某个捕捉器,那么就会保留源对象的默认行为,反之。
Object.defineProperty也可以实现但有很多弊端,有好的咱就尽量用好的,至少我是这样的。

结尾

算是一份回顾基础的笔记吧,没有深究,没必要吧!主要还是记录实现原理,持续更新。

Guess you like

Origin juejin.im/post/7031182760794390565