JavaScript 手写代码 第一期

news2024/12/23 22:38:42

文章目录

  • 1.为什么要手写代码?
  • 2.手写代码
    • 2.1 手写Object.create()方法
      • 2.1.1 基本使用
      • 2.1.2 使用实例
      • 2.1.3 手写实现
    • 2.2 手写实现instanceof方法
      • 2.2.1 基本使用
      • 2.2.2 使用实例
      • 2.2.3 手写实现
    • 2.3 手写实现new操作符
      • 2.3.1 基本使用
      • 2.3.2 使用实例
      • 2.3.3 手写实现

1.为什么要手写代码?

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

2.手写代码

2.1 手写Object.create()方法

2.1.1 基本使用

定义: 静态方法以一个现有对象作为原型,创建一个新对象。
语法

Object.create(proto[, propertiesObject])

第一个参数 proto 表示新创建对象的原型对象。
第二个参数 propertiesObject 可选。如果没有指定为 undefined,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应 Object.defineProperties()的第二个参数。

返回值: 在指定原型对象上添加新属性后的对象。
注意: 如果proto参数不是 null 或一个对象,则抛出一个 TypeError 异常。

2.1.2 使用实例

通过 Object,create() 方法创建了新对象 newObj 并且将新对象newObj的原型对象指向了obj对象,相当于是 newObj.proto == obj 并在第二个参数里面,添加了自己的属性。

//Object.create方法
            let obj = {
                name: 'zs',
                age: 19,
            };

            let newObj = Object.create(obj, {
                hobby: {
                    // 初始化值
                    value: true,
                    // 是否可修改
                    writable: true,
                    // 是否能被删除
                    configurable: true,
                    // 是否可以用 for in 遍历枚举
                    enumerable: true,
                },
            });
            console.log(newObj);
            console.log(newObj.__proto__ == obj);

打印结果输出如下:
在这里插入图片描述

2.1.3 手写实现

通过上面的实列我们知道了 Object.create() 方法在调用过程中进行了怎么样的操作。

  1. 声明一个构造函数(这里为什么要先声明一个构造函数呢?就是因为 f.proto == F.prototype)
  2. 将构造函数的原型对象指向obj(这样可以使得利用F实例化出的实例对象f 的原型对象自然就指向了 obj)
  3. 最后将利用F 实例化后的实例对象 返回即可实现,

具体实现步骤如下

            function create(obj) {
                function F() {}
                F.prototype = obj;
                return new F();
            }

2.2 手写实现instanceof方法

2.2.1 基本使用

instanceof 的用途是判断一个构造函数是否在某个对象原型链上。或者说判断一个对象是某个构造函数的实例。

2.2.2 使用实例

大家先看一段代码,可以想一下会输出什么?

            let str = 'hello';
            console.log(str instanceof String);
            let str1 = new String('world');
            console.log(str1 instanceof String);

结果是
在这里插入图片描述
‘str’ instanceof String,返回值为false,因为 ‘str’ 就是简单的字符串,它和通过String构造函数(new String(‘str’))创造出来的字符串是 有区别 的,

最主要还是判断一个构造函数是否在某个对象的原型链上。

            function Person(name, age) {
                this.name = name;
                this.age = age;
            }
            let person1 = new Person('zs', 19);
            console.log(person1 instanceof Person);
            console.log(person1 instanceof Object);

返回结果均为 true

2.2.3 手写实现

            function myInstanceOf(left, right) {
                // 获取对象的的原型
                let proto = Object.getPrototypeOf(left);
                // 获取构造函数的 prototype 原型对象
                let prototype = right.prototype;
                while (true) {
                    // 说明到达了原型链的终点,说明该构造函数不在该原型对象上
                    if (!proto) return false;
                    if (proto === prototype) return true;
                    // 一直沿着原型链向上查找
                    proto = Object.getPrototypeOf(proto);
                }
            }

2.3 手写实现new操作符

2.3.1 基本使用

new操作符是用来通过构造函数来创建一个实例对象的

2.3.2 使用实例

利用new方法创建了一个构造函数Person的实例对象 person1

            function Person(name, age) {
                this.name = name;
                this.age = age;
            }
            let person1 = new Person('zs', 18);
            console.log(person1);

在这里插入图片描述

2.3.3 手写实现

具体显示思路

  1. 创建了一个空对象;
  2. 将空对象__proto__指向构造函数的原型对象;
  3. 将构造函数中的this绑定到新建的对象obj上并进行初始化
    4.根据构建函数返回类型作判断,如果是原始值则被忽略,如果是返回对象,需要正常处理

            function newObj(Func, ...args) {
                // 创建一个空对象
                let obj = {};
                // 将空对象的__proto__指向构造函数的原型对象
                obj.__proto__ == Func.prototype;
                let result = Func.apply(obj, args);
                return result instanceof Object ? result : obj;
            }
            console.log(newObj(Person, 'zs', 30));

测试手写实现的 newObj 方法

            let person2 = newObj(Person, 'zs', 19);
            console.log(person2);

成功实现
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/674659.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分享一个下载按钮

先看效果&#xff1a; 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>下载按钮</title><link href"https://fonts.googleapis.com/css2?familyHind&amp;d…

Redisson源码-单线程加解锁流程

Redisson源码-单线程加解锁流程 以下源码分析基于redisson-3.17.6版本&#xff0c;不同版本源码会有些许不同需注意。 <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.17.6</version>&l…

推荐5 款好用的 Linux 音乐播放器

目前 Linux 上有几十个音乐播放器&#xff0c;这使得找到一个最好用的变成很困难。之前我们已经回顾了其中的一些播放器&#xff0c;如 Cantata&#xff0c;Exaile&#xff0c;甚至不那么出名的 Clementine&#xff0c;Nightingale 和 Quod Libet。 在本篇文章中我将涵盖更多的…

python学习——pandas数据处理 时间序列案例 matplotlib绘图案例

目录 pandas数据处理1.合并数据1) 堆叠合并2) 主键合并3) 重叠合并 2.分组和聚合3.索引和符合索引4.去除重复值5.处理缺失值6.处理离群值7.标准化数据1) 离差标准化函数2) 标准差标准化函数3) 小数定标差标准化函数 8.转换数据--离散处理9.时间序列【案例】时间序列案例案例1&a…

C++测试

开始对C嘎嘎下手&#xff01; 1.有关char数组 定义长度为5&#xff0c;但是实际长度是定义长度减1 突然就想到计网安全中的栈溢出问题了&#xff0c;C语言是不检查你是否越界的&#xff0c;如果通过让实参溢出覆盖掉原程序的返回地址&#xff0c;通过精心控制是可以让计算机执…

高级数据结构——红黑树

目录 1. 红黑树的概念 2. 红黑树的性质 3. 红黑树 6. 红黑树的验证 7. 红黑树的删除 8. 红黑树与AVL数的比较 9. 红黑树的应用 10. 完整代码 10.1 RBTree.h 10.2 test.cpp 1. 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存…

49天精通Java,第37天,可变参数列表

目录 一、可变参数列表二、可变参数列表的优缺点1、优点2、缺点 三、可变参数列表的适用场景1、函数重载2、命令行参数解析3、集合操作4、函数式编程 大家好&#xff0c;我是哪吒。 &#x1f3c6;本文收录于&#xff0c;49天精通Java从入门到就业。 全网最细Java零基础手把手…

SpringBoot 如何使用 @ResponseStatus 注解处理异常状态码

SpringBoot 如何使用 ResponseStatus 注解处理异常状态码 在 SpringBoot 应用程序中&#xff0c;异常处理是一个非常重要的话题。当应用程序出现异常时&#xff0c;我们需要对异常进行处理&#xff0c;以保证应用程序的稳定性和可靠性。除了使用异常处理器外&#xff0c;Sprin…

重新理解微服务之终究绕不过这4个坎之(一)

写在前头 大家曾经有没有遇过日常技术交流的时候&#xff0c;会讨论某某技术之间的关系是什么&#xff0c;某些技术是否应该用到微服务。我相信热爱技术交流的您&#xff0c;就算不是在微服务这里领域&#xff0c;或多或少都会跟其他同行会做一些争议话题的探讨&#xff0c;而…

华为OD机试真题B卷 JavaScript 实现【字符串分隔】,附详细解题思路

一、题目描述 输入一个字符串&#xff0c;请按长度为8拆分每个输入字符串并进行输出&#xff0c;长度不是8整数倍的字符串请在后面补数字0&#xff0c;空字符串不处理。 二、输入描述 连续输入字符串(每个字符串长度小于等于100)。 三、输出描述 依次输出所有分割后的长度…

k8s使用ceph存储

文章目录 初始化操作k8s使用ceph rbdvolumePV静态pv动态pv k8s使用cephfsvolume静态pv 初始化操作 ceph创建rbd存储池 ceph osd pool create k8s-data 32 32 replicated ceph osd pool application enable k8s-data rbd rbd pool init -p k8s-dataceph添加授权&#xff0c;需…

指针和数组--指针数组及其应用

目录 一、指针数组用于表示多个字符串 二、指针数组用于表示命令行参数 一、指针数组用于表示多个字符串 一维数组可存储一个字符串&#xff0c;二维数组可存储多个字符串。 二维数组的元素在内存中是连续存放的&#xff0c;存完第一行后&#xff0c;再存第二行&#xff0c;以…

多线程之JUC

写在前面 本文一起看下jdk并发包的相关内容。 1&#xff1a;JUC包提供了哪些功能 先通过包结构看下JUC提供的功能&#xff1a; 接下来分别看下。 1.1&#xff1a;锁 JUC中的锁机制提供了比synchronized&#xff0c;wait/notify更加灵活的同步控制&#xff0c;在java.util.…

大数据基础平台实施及运维进阶

1、完全分布式部署介绍 完全分部式是真正利用多台Linux主机来进行部署Hadoop&#xff0c;对Linux机器集群进行规划&#xff0c;使得Hadoop各个模块分别部署在不同的多台机器上。 2、nameNode HA完全分布式部署 2.1、nameNode切换方法 分别处于Active和Standby中 hadoop可以…

操作系统复习笔记4

1、queueType队列类型 队列中的数据也呈线性排列。虽然与栈有些相似&#xff0c;但队列中添加和删除数据的操作分别是在两端进行的。 线性表有顺序存储和链式存储&#xff0c;队列作为一种特殊的线性表&#xff0c;也同样存在这两种存储方式。 1.1 顺序队列 用数组存储队列…

C语言学习(二十五)---指针练习题(一)

在上一节内容中&#xff0c;我们学习了递归与冒泡排序法的有关内容&#xff0c;今天我们将继续往下学习&#xff0c;主要内容为指针练习题&#xff0c;好了&#xff0c;话不多说&#xff0c;开整&#xff01;&#xff01;&#xff01; 在之前的第18—22的内容中&#xff0c;我…

lnmp框架的应用

目录 应用一 nginx访问状态统计 1.先查看http_stub_status有没有安装 2.进入nginx的配置文件改配置 3.nginx-检查配置 重启服务 最后这个20就是显示的状态统计 应用二 给网站加密 1.首先安装http-tools软软件 2.把nginx设置锁也要有执行权限 3.进入nginx配置文件 4. 检查…

【Windows个性化设置篇】StartAllBack更改win11任务栏设置

【Windows个性化设置篇】StartAllBack更改win11任务栏设置 Windows11目前不支持更改任务栏位置固定的修改&#xff0c;因为想把任务栏固定到旁边&#xff0c;从而充分利用电脑屏幕位置。之前试过TranslucentTB可以把任务栏透明化&#xff0c;很漂亮&#xff0c;但在分屏操作时…

【Vue3】Vue3+Vite+TS使用npm包引入百度地图

文章目录 Vue3ViteTS引入百度地图一、注册二、安装依赖包三、参考文档四、全局注册五、局部导入六、断网地图的使用八、项目使用成功图片九、使用卫星图 Vue3ViteTS引入高德地图npm包查找地图依赖包 Vue3ViteTS引入百度地图 一、注册 官网&#x1f449;百度地图开放平台 注册…

python---案例分析(1)

标准库 python自带的 第三方库 其他人做出来的 例1: 实现一个日期计算器 EG: 计算2012年2月14日和2016年2月3日之间的差值 使用datetime 1.根据日期构造出datetime类型的变量 2.把两个变量进行相减,得到的结果即为所求 1) 2) 3) 例2: 实现单词逆序 翻转单词顺序 i am a s…