这些手写代码会了吗?少年

news/2024/7/19 15:14:03 标签: 列表, js, class, prototype, scrum
class="baidu_pl">
class="article_content clearfix">
class="htmledit_views">
class="tags" href="/tags/JS.html" title=js>js_content">

直接开始

手写 call

call 和 apply 的区别:call 方法接收的是一个参数class="tags" href="/tags/LieBiao.html" title=列表>列表,apply 方法接收的是一个包含多个参数的数组。

  • 1.context 存在就使用 context,否则是 window

  • 2.使用 Object(context)context 转换成对象,并通过 context.fnthis 指向 context

  • 3.循环参数,注意从 1 开始,第 0 个是上下文,后面才是我们需要的参数

  • 4.将参数字符串 pushargs

  • 5.字符串和数组拼接时,数组会调用 toString 方法,这样可以实现将参数一个个传入,并通过 eval 执行

  • 6.拿到结果返回前,删除掉 fn

class="has">class="language-go">Function.prototype.call = function(context) {
    context = context ? Object(context) : window;
    context.fn = this;
    let args = [];
    for (let i = 1; i < arguments.length; i++) {
        args.push('arguments['+ i +']');
    }
    let res = eval('context.fn('+ args +')');
    delete context.fn;
    return res;
}

手写 apply

  • 1.apply 无需循环参数class="tags" href="/tags/LieBiao.html" title=列表>列表,传入的 args 就是数组

  • 2.但是 args 是可选参数,如果不传入的话,直接执行

class="has">class="language-go">Function.prototype.apply = function(context, args) {
    context = context ? Object(context) : window;
    context.fn = this;
    if (!args) {
        return context.fn();
    }
    let res = eval('context.fn('+ args +')');
    delete context.fn;
    return res;
}

手写 bind

  • 1.bind 的参数可以在绑定和调用的时候分两次传入

  • 2.bindArgs 是绑定时除了第一个参数以外传入的参数,args 是调用时候传入的参数,将二者拼接后一起传入

  • 3.如果使用 new 运算符构造绑定函数,则会改变 this 指向,this 指向当前的实例

  • 4.通过 Fn 链接原型,这样 fBound 就可以通过原型链访问父类 Fn 的属性

class="has">class="language-go">Function.prototype.bind = function(context) {
    let that = this;
    let bindArgs = Array.prototype.slice.call(arguments, 1);
    function Fn () {};
    function fBound(params) {
        let args = Array.prototype.slice.call(arguments) ;
        return that.apply(this instanceof fBound ? this : context, bindArgs.concat(args));
    }
    Fn.prototype = this.prototype;
    fBound.prototype = new Fn();
    return fBound;
}

手写 new

  • 1.Constructor 就是 new 时传入的第一个参数,剩余的 arguments 是其他的参数

  • 2.使用obj.__proto__ = Constructor.prototype 继承原型上的方法

  • 3.将剩余的 arguments 传给 Contructor ,绑定 this 指向为 obj,并执行

  • 4.如果构造函数返回的是引用类型,直接返回该引用类型,否则返回 obj

class="has">class="language-go">const myNew = function() {
    let Constructor = Array.prototype.shift.call(arguments);
    let obj = {};
    obj.__proto__ = Constructor.prototype;
    let res = Constructor.apply(obj, arguments);
    return res instanceof Object ? res : obj;
}

手写 instanceOf

  • 1.在 left 的原型链中层层查找,是否有原型等于 prototype

  • 2.确定边界条件,如果 left === null,即找到头没找到返回 falseright === left,即找到返回 true

  • 3.left = left.__proto__,不停的向上查找

class="has">class="language-go">const myInstanceof = function(left, right) {
    right = right.prototype;
    left = left.__proto__;
    while (true) {
        if (left === null) {
            return false;
        }
        if (right === left) {
            return true;
        }
        left = left.__proto__;
    }
}

手写 Object.create

  • 新建一个空的构造函数 F ,然后让 F.prototype 指向 obj,最后返回 F 的实例

class="has">class="language-go">const myCreate = function (obj) {
  function F() {};
  F.prototype = obj;
  return new F();
}

 

class="has">class="language-php">◆ ◆ ◆  ◆ ◆
长按关注小生

你的在看我当成喜欢


http://www.niftyadmin.cn/n/1252129.html

相关文章

linux修改.gradle目录,Android Studio Gradle 缓存文件夹设置

通过Gradle自带参数&#xff1a;在 Gradle 官方中曾经有一个BUG&#xff0c;就是说Android-Studio无法成功更改缓存的BUG&#xff0c;后来官方给的答案就是采用 Gradle 自己的命令行进行更改。在Gradle的命令行中有&#xff1a;-g 和 –gradle-user-home 这两个命令的作用一样&…

一步步从头搭建 Vue 开发环境

前言由于是工具&#xff0c;很可能你看到的时候有些工具包已经升级了&#xff0c;会有一些报错&#xff1b;这个你就需要自己探索了。工具的版本node: v10.16.0npm: v6.9.0babel: 7.5.5webpack: 4.38.0入题提醒&#xff1a;在我们开始之前&#xff0c;你先检查下你相关工具的包…

linux下3690端口启动,LINUX下svn安装部署

1.#安装yum install subversion2.#测试svnserve --version3.#创建库根路径mkdir /usr/local/svn4.#创建一个项目库svnadmin create /usr/local/svn/project5.修改配置文件cd /usr/local/svn/projectvi svnserve.conf[general]anon-accessnone------------- #没有登录不能操作au…

「翻译」Vue3 相比 Vue2 都有哪些优化?

在过去的一年中&#xff0c;Vue 团队一直在研究 Vue.js 的下一个主要版本&#xff0c;我们希望在 2020 年上半年发布该版本。&#xff08;在撰写本文时&#xff0c;这项工作仍在进行中。&#xff09;Vue 的新的主要版本的构想形成于 2018 年年末&#xff0c;当时 Vue 2 的代码库…

linux系统运行pbs出现ntf,Amber 教程

研究案例——一种稳定蛋白质的全部原子结构预测和折叠模拟这段教程展示的是一个研究实例&#xff0c;像您演示如何重现下述文章中的研究工作&#xff1a;Simmerling, C., Strockbine, B., Roitberg, A.E., J. Am. Chem. Soc., 2002, 124, 11258-11259(http://www.doczj.com/doc…

8月最新:4个前端精选面试题(含答案解析)

网上的面试题一大堆&#xff0c;鱼龙混杂&#xff0c;一方面多数题目质量不高&#xff0c;另一方面有答案的很少&#xff0c;即使拿到面试题对自己的帮助也不大。最近我花了一点时间&#xff0c;为大家整理了8月面试的过程中遇到的4个值得分享的前端面试题&#xff0c;内容包括…

linux进程监控提醒,linux进程监控,monitor脚本

由于服务器上一些进程莫名的挂掉&#xff0c;需要些一个monitor的bash脚本来监控这些进程:#! /bin/bash#chkconfig info### BEGIN INIT INFO# Provides:# Default-Start:# Default-Stop:# Description:### END INIT INFOMYSQL_NAMEmysqlAPACHE_NAMEhttpfunction check_process …

十分钟上手ES2020新特性

前言ES2020 是 ECMAScript 对应 2020 年的版本。这个版本不像 ES6 (ES2015)那样包含大量新特性。但也添加了许多有趣且有用的特性。本文的代码地址&#xff1a;https://github.com/ljianshu/Blog本文以简单的代码示例来介绍 ES2020新特性。这样&#xff0c;你可以很快理解这些新…