JS高级代码合集

目录

一、深克隆

二、闭包

三、函数科里化

四、xhr的二次封装

4.1、普通封装

4.2、promise封装

五、axios的二次封装


一、深克隆

野路子方案

  • 克隆不了对象之中的函数,除此之外对象之中的所有数据都可以实现深克隆
console.log( JSON.parse( JSON.stringify( 数组名/对象名 ) ))

递归方案

  • 解决了野路子方案存在的问题
function deepClone( obj ){
    let clone = obj instanceof Array ? [] : {};
    for( let attr in obj ){
        if( typeof obj[attr] === "Object" ){
            clone[attr] = deepClone( obj[attr] );
        }else{
            clone[attr] = obj[attr];
        }
    }
    return clone;
}

let obj5 = { a:{},b:[],c: function(){} };
let clone3 = deepClone( obj5 );
console.log( "clone3:",clone3 );

二、闭包

形成闭包的规则

同时满足了下面的规则的话,活动对象就不会被删除:

  1. 外部函数包裹内部函数;

  2. 外部函数返回内部函数;( 暴露 )

  3. 外部函数声明的变量在内部函数之中被引用;

这种情况我们称之为闭包;

代码

// 外部函数
function outerFn( b ){
    // 声明变量
    let a = 10;

    // 内部函数
    function innerFn(){
        // 注意: 外部函数的参数( 形参 )也遵闭包机制进行改变;
        console.log( a,b );
    }

    // 我们需要返回内部函数
    return innerFn;
}

三、函数科里化

科里化函数封装思路

  1. 科里化函数传入目标函数作为参数

  2. 科里化函数封装返回常规函数的科里化函数

  3. 我们判定当前调用科里化函数的时候传入了多少个参数

    1. 如果传入参数和目标参数相同,则调用目标函数,完成计算结果

    2. 如果传入参数没有到达既定的参数数量,我们就继续返回函数

代码

// 常规函数
function foo( a,b,c ){
    return a + b + c;
}



// 科里化函数
function curry(fn) {
    // 在外部记录当前的参数传入了多少
    // 记录当前的目标函数的参数数量
    let args = [];
    let { length } = fn;

    // 在内部使用闭包:
    function curry_fn(...arg) {
        args.push(...arg);

        // 如果args数量没有达到目标参数的数量, 那么我们返回当前的函数; 
        if (args.length < length) {
            return "参数不够";
        } else {
            // 如果参数数量足够了那么我们就调用目标函数执行功能;
            return fn(...args);
        }
    }
    return curry_fn;
}

四、xhr的二次封装

4.1、普通封装

思路

  1. 提取需要改变的数据作为参数来进行封装

  2. 请求方式需要改变!【method】

  3. 请求路径需要改变!【url】

  4. 请求数据需要改变!【data】

  5. 请求头需要改变!  【headers】

  6. 响应数据处理需要改变!(重要)回调函数!【callback】

响应数据为什么需要改变,因为我们不知道我们拿到的数据类型是txt还是JSON,

如果是JSON需要格式化,而txt纯文本则不需要

代码

  • 封装
// 对于多参数封装我们要把参数放在对象之中
// -. 封装xhr工具
function xhr(options) {
    options = {
        // 前面写默认参数
        // -. 请求方式
        method: "GET",
        // -. 请求路径
        utl: "",
        // -. 请求携带数据
        data: {},
        // -. 请求头
        headers: {},
        // - 响应数据的处理方式 : 
        // - text / json 
        dataType: "json",
        // -. 响应处理函数
        callback: function () { },
        // 后面携带的是用户参数
        ...options
    };

    // 注意: 我们只需要formattedDate加工data数据,并不需要返回值,所以不需要写return语句,当然写也没什么。
    formattedDate(options);
    // -. 查看格式化后的data数据
    // console.log( options.data );


    // 1. xhr发起请求
    // -. 创建xhr实例对象( 这里没有任何需要改变的地方 )
    let xhr = new XMLHttpRequest();

    // -. 配置xhr对象
    // 注意: 我们请求携带数据,如果请求方式是GET,那么数据需要放到url路径上;(将数据和url路径拼接在一起)
    if (options.method.toUpperCase() === "GET" && options.data) {
        options.url += "?" + options.data;
        xhr.open(options.method, options.url);
    }
    xhr.open(options.method, options.url);

    // -. 请求头
    for (let attr in options.header) {
        console.log(1);
        console.log(attr)
        // 调用一次setRequestHeader设置一条请求头信息
        xhr.setRequestHeader(attr, options.header[attr]);
    }

    // -. 请求体
    // 判断当前的请求方式是不是POST,如果是POST同时携带数据我们把数据放在send参数之中;
    if (options.method.toUpperCase() === "POST" && options.data) {
        xhr.send(options.data);
    } else {
        xhr.send();
    }

    // 2. xhr响应处理
    xhr.onload = function () {
        let data = xhr.responseText;
        // 把响应数据处理格式进行逻辑判断
        switch (options.dataType) {
            case "json":
                data = JSON.parse(data);
                break;
        }
        options.callback(data);
    }

}

// 格式化数据
function formattedDate( options ){
    let data = "";
    for( let attr in options.data ){
        data += `&${attr}=${options.data[attr]}`
    }
    options.data = data.slice( 1 )
}
  • 使用
function sendRequest() {
    // 传递请求的配置参数
    let options = {
        method: "POST",
        url: "http://localhost:8888/test/fourth",
        data: {
            name: "jack",
            age: 16
        },
        header: {
            "Content-Type": "applicationx-www-form-urlencoded",
        },

        callback(data) {
            console.log("这是响应数据:", data)
        }

    }
    xhr(options);
}

let btn = document.getElementById("btn");
btn.addEventListener("click", sendRequest);

4.2、promise封装

Promise封装核心

  1. 让xhr函数的返回值是一个Promise对象

  2. 让响应数据获取结束之后改变Promise对象的状态

  3. 响应数据作为Promise对象的数据进行放入!

 注意: 要把异步程序放入到Promise对象之中;(Promise对象的状态改变都是在异步异步程序完成的);

代码

  • 封装
// xhr工具封装
function xhr(options) {
    options = {
        // -. 请求方式
        method: "GET",
        // -. 请求路径
        url: "",
        // -. 数据
        data: {},
        // -. 请求头
        headers: {},
        // -. 响应数据类型
        dataType: "json",
        // -. 回调函数( 响应处理 )
        callback: function () { },
        ...options
    }

    // 数据格式化
    formattedDate(options);
    // console.log( options.data )

    // 1. 发送请求
    // -. 创建xhr实例对象
    let xhr = new XMLHttpRequest();
    // -. 配置xhr对象
    if (options.method.toUpperCase() === "GET" && options.data) {
        options.url += "?" + options.data;
        xhr.open(options.method, options.url);
    } else {
        xhr.open(options.method, options.url);
    }

    // -. 设置请求头
    for (let attr in options.headers) {
        xhr.setRequestHeader(attr, options.headers[attr]);
    }
    // -. 设置请求体( 发送数据 )
    if (options.method.toUpperCase() === "POST" && options.data) {
        xhr.send(options.data);
    } else {
        xhr.send();
    }

    // 响应数据处理:
    // -. 因为响应数据处理都是异步的,所以我们把异步程序放入到Promise对象之中
    // -. 在获取到响应数据之后,改变Promise对象的状态

    // 2. 响应处理
    return new Promise(resolver => {
        xhr.onload = function () {

            let data = xhr.responseText;
            switch (options.dataType) {
                case "json":
                    data = JSON.parse(data);
                    break;
            }
            options.callback(data);

            // 改变Promise对象状态:
            // -. callback可以保留, 因为这个callback并不影响我们程序执行
            resolver(data);
        }
    })

}

// 加工数据
function formattedDate(options) {
    let data = "";
    for (let attr in options.data) {
        data += `&${attr}=${options.data[attr]}`;
    }
    options.data = data.slice(1);
}
  • 使用(async await 处理Promise响应数据!(推荐))
let btnNode = document.getElementById( "btn" );

// async await 处理Promise响应数据!(推荐)
async function sendRequest(){
    let options = {
        method: "POST",
        url: "http://localhost:8888/test/fourth",
        data:{
            name: 'jack',
            age: 18
        },
        headers:{
            "Content-Type": "application/x-www-form-urlencoded"
        },
        // callback( data ){
        //     console.log( "这是响应数据:",data )
        // }
    }
    let data = await xhr( options );
    console.log( data )
}

btnNode.addEventListener( "click",sendRequest );
  • 使用( then使用Promise对象)
let btnNode = document.getElementById( "btn" );

// then使用Promise对象
function sendRequest(){
    let options = {
        method: "POST",
        url: "http://localhost:8888/test/fourth",
        data:{
            name: 'jack',
            age: 18
        },
        headers:{
            "Content-Type": "application/x-www-form-urlencoded"
        },
        // callback( data ){
        //     console.log( "这是响应数据:",data )
        // }
    }
    // 注意: xhr函数的返回值是一个Promise对象
    xhr( options )
    .then( data=>{console.log( data )} )
}

btnNode.addEventListener( "click",sendRequest );

五、axios的二次封装

封装思路

  1. 配置基础路径和超时时间

  2. 请求拦截(显示进度条)

  3. 响应拦截(关闭进度条)

  4. 导出二次封装

注意:二次封装的axios里面的配置项都是固定配置选项,不是随意取名的

代码

  1. 进度条需要借助node安装

// 引入axios
import Axios from 'axios';
import base from './base.js';
// = 进度条
import NProgress from 'nprogress';
// = 使用 nprogress的css样式
import "nprogress/nprogress.css";

// 1. 配置基础路径和超时时间
const instance = Axios.create({
    // = 基础路径( baseURL )
    // baseURL: "http://localhost:3000",
    baseURL: base.hostURL,
    // = 超时时间( timeout 单位ms )
    timeout: 5000
})



// 2. 请求拦截
// = 开启进度条
instance.interceptors.request.use(
    (config)=>{
        NProgress.start();
        return config;
    },
    (err)=>{
        return Promise.reject(err);// '错误' false
    }
);


// 3. 响应拦截
// = 关闭进度条
instance.interceptors.response.use(
    (res)=>{
        NProgress.done();
        return res;
    },
    (err)=>{
        // - Promise.reject() 方法返回一个带有拒绝原因的 Promise 对象。
        // = err就是:Promise对象失败状态传递参数为err
        // = err就是状态改变传递的实参
        // = then监听工具会有形参接收的
        return Promise.reject(err)
    }
);


// 4. 导出二次封装
export default instance;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值