JavaScript 手写代码 第三期

简介: JavaScript 手写代码 第三期

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}

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

目录
相关文章
|
2月前
|
JavaScript
短小精悍的js代码
【10月更文挑战第17天】
129 58
|
2月前
|
JavaScript 前端开发 开发者
如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 来检查代码规范并自动格式化 Vue.js 代码。
【10月更文挑战第7天】随着前端开发技术的快速发展,代码规范和格式化工具变得尤为重要。本文介绍了如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 来检查代码规范并自动格式化 Vue.js 代码。通过安装和配置这两个工具,可以确保代码风格一致,提升团队协作效率和代码质量。
270 2
|
2月前
|
JavaScript 前端开发 内存技术
js文件的入口代码及需要入口代码的原因
js文件的入口代码及需要入口代码的原因
45 0
|
17天前
|
JavaScript 前端开发 测试技术
在 golang 中执行 javascript 代码的方案详解
本文介绍了在 Golang 中执行 JavaScript 代码的四种方法:使用 `otto` 和 `goja` 嵌入式 JavaScript 引擎、通过 `os/exec` 调用 Node.js 外部进程以及使用 WebView 嵌入浏览器。每种方法都有其适用场景,如嵌入简单脚本、运行复杂 Node.js 脚本或在桌面应用中显示 Web 内容。
51 15
在 golang 中执行 javascript 代码的方案详解
|
3月前
|
编解码 前端开发 JavaScript
javascript检测网页缩放演示代码
javascript检测网页缩放演示代码
|
1月前
|
JavaScript
原生js炫酷随机抽奖中奖效果代码
原生js随机抽奖是一个炫酷的根据数据随机抽奖的代码,该网页可进行随机抽取一个数据,页面动画高科技、炫酷感觉的随机抽奖效果,简单好用,欢迎下载!
46 3
原生js炫酷随机抽奖中奖效果代码
|
21天前
|
JSON JavaScript 关系型数据库
node.js连接GBase 8a 数据库 并进行查询代码示例
node.js连接GBase 8a 数据库 并进行查询代码示例
|
1月前
|
JavaScript 前端开发 开发者
如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码,包括安装插件、配置 ESLint 和 Prettier 以及 VSCode 设置的具体步骤
随着前端开发技术的快速发展,代码规范和格式化工具变得尤为重要。本文介绍了如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码,包括安装插件、配置 ESLint 和 Prettier 以及 VSCode 设置的具体步骤。通过这些工具,可以显著提升编码效率和代码质量。
449 4
|
1月前
|
JSON 移动开发 数据格式
html5+css3+js移动端带歌词音乐播放器代码
音乐播放器特效是一款html5+css3+js制作的手机移动端音乐播放器代码,带歌词显示。包括支持单曲循环,歌词显示,歌曲搜索,音量控制,列表循环等功能。利用json获取音乐歌单和歌词,基于html5 audio属性手机音乐播放器代码。
110 6