本文介绍: 我们日常开发过程中,往往都是取出来直接用,从来不思考代码底层实现逻辑,但当我开始研究一些底层的东西的时候,才开始理解了JavaScript每个方法函数底层实现思路,我认为这可以很好的提高我们代码水平和逻辑思维sources 里面对象属性,依次添加目标对象上,遇到相同属性目标对象的属性值直接被覆盖最后返回目标对象合并后的值,并且 目标对象的值 也会被改变。注意:如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。细心的大家可以发现目标对象里面的值被源对象里面的值覆盖了。

1. 为什么手写代码

我们日常开发过程中,往往都是取出来直接用,从来不思考代码底层实现逻辑,但当我开始研究一些底层的东西的时候,才开始理解了JavaScript每个方法和函数的底层实现思路,我认为这可以很好的提高我们的代码水平和逻辑思维

2. 手写代码

2.1 函数柯里化

2.1.1 基本使用

函数柯里化指的是一种将多个参数一个函数转换成系列使用一个参数的函数的技术

            // 正常使用
            function sum(a, b, c) {
                return a + b + c;
            }
            console.log(sum(1, 2, 3));
            
            // 函数柯里化实现上面的操作
            function sum1(a) {
                return function (b) {
                    return function (c) {
                        return a + b + c;
                    };
                };
            }
            console.log(sum1(1)(2)(3));

函数柯里化其实就是利用闭包,大家想了解闭包可以转到我的博文 闭包

2.1.2 手写实现

            function curry(fn, ...args) {
                let length = fn.length;
                args = args || [];
                return function () {
                    let subArgs = args.slice(0);
                    // 合并所有的参数
                    subArgs = [...subArgs, ...arguments];
                    // 判断参数长度是否已经满足函数所需要长度
                    if (subArgs.length >= length) {
                        return fn.apply(this, subArgs);
                    } else {
                        // 返回柯里化化函数,等待继续传递参数
                        return curry.call(this, fn, ...subArgs);
                    }
                };
            }

可以进行测试
传入方法sum

          function sum(a, b, c) {
                return a + b + c;
          }

发现可以正常打印结果,成功实现 函数柯里化

            let add = curry(sum);
            console.log(add(1)(1, 2, 3)); // 6
            console.log(add(1)(2)(3)); // 6
            console.log(add(1, 2, 3));
            console.log(add()(1, 2, 3));

函数柯里化的简单实现方法
一行代码搞定

function curry1(fn, ...args) {
	return fn.length <= args.length ? fn(...args) : curry1.bind(null, fn, ...args);
}

主要利用bind在改变this指向的同时,也可以传递参数
例如下就可以理解

            function fn(a, b, c) {
                console.log(a, b, c);
            }
            let fn1 = fn.bind(null, 1, 2);
            fn1(3); // 1,2,3

正常打印出了 1,2,3

2.2 sleep函数

2.2.1 简单使用

sleep是一种函数作用延时程序暂停若干时间,在执行时要抛出一个中断异常,必须对其进行捕获处理才可以使用这个函数。
js 中是没有这个函数的,需要我们手写实现使用

2.2.2 手写实现

方法一 利用promise异步处理定时器

            function sleep(delay) {
                return new Promise((resolve) => {
                    setTimeout(resolve, delay);
                });
            }
            sleep(1000).then(() => {
                console.log('111');
            });

一秒打印出111
方法二 利用定时器setTimeout回调函数写法

            function sleep(delay, callback) {
                setTimeout(callback, delay);
            }
            sleep(1000, () => {
                console.log(1000);
            });

方法三 利用了Date函数时间写法精确计算

            function sleep(delay) {
                let startTime = new Date().getTime();
                while (new Date().getTime() - startTime < delay) {
                    // 只要还没有到特定事件,就一直在循环内,
                    // 到了规定延迟后,跳出循环指向下面的方法
                    continue;
                }
            }
            console.log('1111');
            sleep(5000);
            console.log('2222');

2.3 Object.assign() 方法

2.3.1 基本使用

Object.assign() 方法用于将所有可枚举属性的值从一个多个源对象复制目标对象。它将返回目标对象。

Object.assign(target,sources) 

第一个参数target: 即目标对象,目标对象的值会发生改变。
第二个参数souce:源对象(可多个)源对象不会发生改变

2.3.2 具体示例

            let obj = { name: 'zs' };
            let obj1 = { name: 'lisi' };
            let obj2 = { age: 20 };
            let newObj = Object.assign(obj, obj1, obj2);
            console.log(newObj); // {name: 'lisi', age: 20}
            console.log(obj);  // {name: 'lisi', age: 20}
            console.log(obj1); // {name: 'lisi'}
            console.log(obj2); // {age: 20}

细心的大家可以发现,目标对象里面的值被源对象里面的值覆盖了。

注意:如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性

2.3.3 具体思路

大家通过上面的示例不能发现 Objec.assign() 到底干了什么通过 遍历 sources 里面的对象属性,依次添加到 目标对象上,遇到相同的属性,目标对象的属性值直接被覆盖最后返回目标对象合并后的值,并且 目标对象的值 也会被改变。

2.3.4 具体实现

知识: Object.assign()方法在Object 对象上,并不是在它的原型对象上,myAssign()加粗表示我们新增的方法,而 assign自带的方法
在这里插入图片描述

            Object.myAssign = function (target, ...sources) {
                if (target == null) {
                    throw new TypeError('Cannot convert undefind or null to object');
                }
                sources.forEach((source) => {
                    if (source != null) {
                        // 遍历一个对象里面的属性,会遍历原型上面的属性
                        for (let key in source) {
                            // 判断该属性是不是对象自身的属性
                            if (source.hasOwnProperty(key)) {
                                target[key] = source[key];
                            }
                        }
                    }
                });
                // 将合并后的对象返回即可
                return target;
            };

测试上面实现的代码

            let newObj = Object.myAssign(obj, obj1, obj2);
            console.log(newObj); // {name: 'lisi', age: 20}
            console.log(obj); // {name: 'lisi', age: 20}
            console.log(obj1); // {name: 'lisi'}
            console.log(obj2); // {age: 20}

打印输出结果完成,成功实现。

欢迎大家在讨论学习,感谢大家支持

原文地址:https://blog.csdn.net/qq_63299825/article/details/131348023

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_34066.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注