JS中call方法是什么,call()的原理是什么?如何手写一个call()?Symbol是什么,怎么用Symbol调优?含详细解析

news2024/9/24 19:23:06

🎉call()

💕call()的参数

thisArg:在调用 func 时要使用的 this 值
arg1, …, argN (可选) 函数的参数

✨call()的描述:

首先声明 func是一个函数,person是一个对象
针对这段代码:func.call(person,‘a1’,‘a2’)
调用func方法并传递两个参数’a1’,‘a2’ ,以及把func中的this设置为person对象

🍧call()的代码解释

 function greet (a,b) {
	  console.log(this)
      console.log(this.animal, "的睡眠时间一般在", this.sleepDuration, "之间",a, b)
    }

    const obj = {
      animal: "猫",
      sleepDuration: "12 到 16 小时",
    }

    greet.call(obj, "哦", "!!!") // {animal: '猫', sleepDuration: '12 到 16 小时'}
    //猫 的睡眠时间一般在 12 到 16 小时 之间 哦 !!!

🎡手写Call() :myCall()

❤️步骤

手写Call() 分为四步

  1. 定义myCall方法,加在Function原型上,使得所有函数都能点出来使用
  2. 设置this并调用原函数
  3. 接收剩余参数并返回结果
  4. 使用Symbol调优

🎶前置知识 this指向问题

  1. 全局执行环境中,指向全局对象window(非严格模式、严格模式)

  2. 函数内部,取决于函数被调用的方式
    2.1. 直接调用的this值:

    • 非严格模式:全局对象(window)
    • 严格模式:undefined

    2.2 对象方法调用的this值:

    • 调用者
  3. 开启严格模式

    • 脚本开启: ‘use strict’
    • 函数内部开启:‘use strict’
    • 注意:'use strict’写在代码顶端
 // ------------- 1.全局执行环境 -------------
    //  严格模式,非严格模式 全局对象(window)
    // 'use strict'
    // console.log(this)

    // ------------- 2.函数内部 -------------
    // 2.1 直接调用-非严格模式
    // function func() {
    //   console.log(this) // window
    // }
    // func()
    // 2.1 直接调用-严格模式
    // function func() {
    //   'use strict'
    //   console.log(this) // undefined
    // }
    // func()

    // 2.2 对象方法调用
    const food = {
      name: '猪脚饭',
      eat() {
        'use strict'
        console.log(this)
      }
    }
    // 非严格模式,严格模式
    food.eat() // 调用者 Object {eat: ƒ eat(),name: "猪脚饭"}

再来看一下MDN的解释 MDN地址

✨下面这点很重要

o.f() 就使得 函数 f 中的 this 指向 对象 o

在这里插入图片描述
先定义一个对象o,在定义一个函数independent(),然后把函数追加到对象o中和上述可以实现一样的效果
在这里插入图片描述

🎀第一步:定义myCall方法,加在Function原型上,使得所有函数都能点出来使用

在Function对象的原形上通过"."的方式添加myCall属性,并给这个对象赋值一个函数

  Function.prototype.myCall = function () {
      console.log("this is myCall")
    }
    function greet () { }
    greet.myCall()// this is myCall

🎶第二步:设置this并调用原函数

🎐图解

在这里插入图片描述
由于给person多加了一个f属性,所以后面需要使用 delete关键词 把f属性删掉

🎏代码

     
    Function.prototype.myCall = function (thisArg) {
      thisArg.f = this //这个this就是原函数func(因为 根据前置知识的讲解 func.mycall()使得函数myCall的this指向func )
      // ,这段代码是在person(thisArg在这里就是person)对象上面增加一个属性,属性名为f 属性值为func(){...}
      thisArg.f()//根据前置知识 f的this是thisArg,在这里f是func 这样就完成了第二步
 
      

    }
    // ------------- 测试代码 -------------
    const person = {
      name: 'zhangsan'
    }
    function func (numA, numB) {
      console.log(this)
      console.log(numA, numB)
      return numA + numB
    }
    const res = func.myCall(person) // {name: 'zhangsan', f: ƒ}


🎄第三步:接收剩余参数并返回结果

使用…args接收剩余参数,并用解构赋值的方法把参数传递给调用者


    Function.prototype.myCall = function (thisArg, ...args) {
      thisArg.f = this  
      const res = thisArg.f(...args) //args=>[2,8] ...args=>2,8 把剩余参数传给func (numA=2,numB=8)
      delete thisArg.f //删除person中新加的f属性
      return res
    }
   

    // ------------- 测试代码 -------------
    const person = {
      name: 'zhangsan'
    }
    function func(numA, numB) {
      console.log(this) //Object{name:zhangsan}
      console.log(numA, numB) //2 8
      return numA + numB
    }
    const res = func.myCall(person, 2, 8)
    console.log('返回值为:', res) // 返回值为: 10


在这里插入图片描述

🍿 测试

    Function.prototype.myCall = function (thisArg, ...args) {
      thisArg.f = this
      const res = thisArg.f(...args) 
      delete thisArg.f 
      return res
    }

// ------------- 测试代码 -------------
    const student = {
      name: 'lisi'
    }
    function func2 (a, b, c) {
      console.log(this)
      console.log(a, b, c)
      return a + b + c
    }
    const res2 = func2.myCall(student, 1, 2, 3)
    console.log('返回值:', res2)

在这里插入图片描述

✨第四步:使用Symbol调优

🎶关于Symbol

Symbol的MDN链接

symbol 是一种基本数据类型(primitive data type)。
Symbol() 函数会返回 symbol类型的值,该类型具有静态属性和静态方法。

每个从 Symbol() 返回的 symbol 值都是唯一的。一个 symbol 值能作为对象属性的标识符;

🍧symbol的使用

直接使用Symbol()创建新的 symbol 类型,并用一个可选的字符串作为其描述。这个描述只是为了看着方便没有实际用处。(MDN解释:对 symbol 的描述,可用于调试但不是访问 symbol 本身。)

var sym1 = Symbol();
var sym2 = Symbol("foo");
var sym3 = Symbol("foo");
// 这三个都不相等
   Function.prototype.myCall = function (thisArg, ...args) {
       
      const key = Symbol('key')// 使用Symbol创建一个唯一的symbol值 作为对象的标识符
      // thisArg.key 是给thisArg对象增加一个名为字符串'key'的属性
      thisArg[key] = this //thisArg[key] 是把key作为一个变量 实际传过去的是Symbol('key')
      const res = thisArg[key](...args)
      delete thisArg[key]
      return res
    }
    
    

🎉测试

   Function.prototype.myCall = function (thisArg, ...args) {
       
      const key = Symbol('key')// 使用Symbol创建一个唯一的symbol值 作为对象的标识符
      // thisArg.key 是给thisArg对象增加一个名为字符串'key'的属性
      thisArg[key] = this //thisArg[key] 是把key作为一个变量 实际传过去的是Symbol('key')
      const res = thisArg[key](...args)
      delete thisArg[key]
      return res
    }
   // ------------- 测试代码 -------------
 	const student = {
      name: 'lisi'
    }
    function func2 (a, b, c) {
      console.log(this)
      console.log(a, b, c)
      return a + b + c
    }
    const res2 = func2.myCall(student, 1, 2, 3)
    console.log('返回值:', res2)

这个是谷歌浏览器的结果,谷歌这点有点显示bug
在这里插入图片描述

Edge就没有,下图是Edge浏览器的结果
在这里插入图片描述

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

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

相关文章

SSL证书系列--DV、OV、EV三种证书类型的区别

原文网址:SSL证书系列--DV、OV、EV三种证书类型的区别_IT利刃出鞘的博客-CSDN博客 简介 本文介绍DV、OV、EV这三种SSL证书的区别。 DV、OV、EV的区别 项 DV OV EV 英文全称 Domain Validation (域名验证型证书) Organization Valida…

前端的规范

假如团队中的小伙伴在提交代码时没有遵循规范要求,只写了一个"fix"或"update,这会给其他小伙伴造成困扰,不得不花时间查看代码和推测逻辑。 不仅会浪费了时间和精力,可能会导致项目以下问题: 可读性差…

知网被网信办罚款5000万

我是卢松松,点点上面的头像,欢迎关注我哦! 9月6日,知网被网信办罚款5000万,对此,知网称,诚恳接受,坚决服从。 去年(2022年)知网被市场监管总局以垄断行为对其开出了8760万元的罚单…

zabbix监控网络设备和zabbix proxy代理

使用snmp监控linux主机 #在被监控端安装SNMP协议 [rootrocky8 conf]# yum -y install net-snmp 修改配置 vim /etc/snmp/snmpd.conf com2sec notConfigUser default 123456 ##修改此行,设置团体密码,默认为public,此处 改为123456 view systemview included .1. ##添加此行,自…

微信小程序中识别html标签的方法

rich-text组件 在微信小程序中有一个组件rich-text可以识别文本节点或是元素节点 具体入下: //需要识别的数据放在data中,然后放在nodes属性中即可 <rich-text nodes"{{data}}"></rich-text>详情可以参考官方文档:https://developers.weixin.qq.com/mi…

软件测试/测试开发丨跨平台 api 对接 学习笔记

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27139 跨平台 api 对接 测试平台需求 稳定 功能 调用脚本报告获取分布式支持 API 调用 开源 Jenkins 环境准备 Jenkins 满足所有调度平台的需求 需…

如何让自己的精力集中 Maven自学笔记 马云演讲观看

目录 如何让自己的精力集中 Avoid having multiple tasks and objects in your line of sight 人的脑袋是给自己思考用的 晚上床上想千条路&#xff0c;早上起床还是走原路 参与才会变得更好 共度灾难&#xff0c;是需要互相鼓励的 CFO Capital 上海各区都有哪些大学?…

晨启,MSP430开发板,51开发板,原理图,PCB图

下载&#xff1a;https://github.com/xddun/blog_code_search

纯手工总结超详细关于计算机网络的五层知识点,看看你都掌握了没

纯手工总结超详细关于计算机网络的五层知识点&#xff0c;看看你都掌握了没 文章目录 纯手工总结超详细关于计算机网络的五层知识点&#xff0c;看看你都掌握了没1.应用层1.1 HTTP协议1.1.1 URL1.1.2 HTTP方法1.1.3 HTTP请求1.1.4 HTTP状态码1.1.5 HTTP会话保持 1.2 HTTPS协议 …

软考高级之系统架构师之计算机硬件基础与嵌入式系统

今日&#xff1a;2023年09月07日&#xff0c;离软考高级仅剩57天。 计算机硬件基础 计算机系统中的存储部件通常组织成层次结构&#xff0c;越接近CPU的存储部件访问速度越快。存储速度从快到慢分别是&#xff1a;寄存器组、Cache、内存、Flash。 计算机执行程序时&#xff…

【AI理论学习】语言模型:从Word Embedding到ELMo

语言模型&#xff1a;从Word Embedding到ELMo ELMo原理Bi-LM总结参考资料 本文主要介绍一种建立在LSTM基础上的ELMo预训练模型。2013年的Word2Vec及2014年的GloVe的工作中&#xff0c;每个词对应一个vector&#xff0c;对于多义词无能为力。ELMo的工作对于此&#xff0c;提出了…

视频讲解|3014 含分布式电源的配电网优化重构

目录 1 主要内容 2 讲解视频链接 3 部分程序 1 主要内容 该视频为程序目录中编号1034的讲解内容&#xff0c;该程序的链接为配电网优化重构matlab智能算法&#xff0c;本次重点讲解了基本环矩阵原理以及代码两步实现过程、如何利用基本环向量去创造可行解、粒子群优化过程、…

GeoNet: Unsupervised Learning of Dense Depth, Optical Flow and Camera Pose 论文阅读

论文信息 题目&#xff1a;GeoNet: Unsupervised Learning of Dense Depth, Optical Flow and Camera Pose 作者&#xff1a;Zhichao Yin and Jianping Shi 来源&#xff1a;CVPR 时间&#xff1a;2018 Abstract 我们提出了 GeoNet&#xff0c;这是一种联合无监督学习框架&a…

Kafka3.0.0版本——消费者(消费者组案例)

目录 一、消费者组案例1.1、案例需求1.2、案例代码1.2.1、消费者1代码1.2.2、消费者2代码1.2.3、消费者3代码1.2.4、生产者代码 1.3、测试 一、消费者组案例 1.1、案例需求 测试同一个主题的分区数据&#xff0c;只能由一个消费者组中的一个消费。如下图所示&#xff1a; 1…

[CISCN 2019华北Day1]Web1

文章目录 涉及知识点解题过程 涉及知识点 phar反序列化文件读取 解题过程 打开题目&#xff0c;注册用户为admin 进去发现有文件上传的功能&#xff0c;我们随便上传个图片 然后就有下载和删除两个功能 我们尝试抓包下载文件的功能 发现参数可控&#xff0c;我们尝试读取一下…

C++如何查看栈的变量

在如下行下断点&#xff0c;然后运行&#xff0c;中断&#xff1b; 右击中断的代码行&#xff0c;选择 转到反汇编&#xff1b; 红线标示的行是调用AddNum()函数处&#xff1b;看一下之前使用了push把a和b压入栈&#xff1b;使用push压入栈的变量就是放入栈的变量&#xff1b; …

Net跨平台UI框架Avalonia入门-安装和使用(v11版本)

介绍Avalonia v11版本 avalonia v11版本发布了&#xff0c;增加了很多新的功能&#xff0c;Avalonia的扩展也同步升级了。 主要更新内容&#xff1a; 辅助功能&#xff1a;增加了对各种辅助工具的支持&#xff0c;提高了Avalonia应用程序的可用性。输入法编辑器&#xff08;I…

模型压缩-对模型结构进行优化

模型压缩-对模型结构进行优化 概述 模型压缩通常都是对推断过程而言&#xff0c;训练过程的计算代价通常不考虑&#xff0c;因为GPU可以快速完成任意复杂度模型的训练对于推断过程来说&#xff0c;模型应用才是对于速度敏感的场景多数情况下 希望使用尽可能少的能耗完成京可能…

通俗讲解傅里叶变换

参考:六一礼物:给孩子解释什么是傅里叶变换 牛!不看任何数学公式来讲解傅里叶变换 如何直观形象、生动有趣地给文科学生介绍傅里叶变换? - 知乎 从基说起…… 从数学的角度,提供一个形象有趣的解释。理解傅里叶变换的钥匙是理解基♂,它能让你重新认识世界。 1. 什么是…

概率有向图模型(一)

文章目录 前言概率有向图模型验证回到书中隐马尔可夫模型信念网络朴素贝耶斯 总结 前言 经过前面的复习&#xff0c;我们把李航老师的《统计学习方法》中的监督学习部分回顾了一遍&#xff0c;接下来我们在此基础上&#xff0c;开始学习邱锡鹏老师的《神经网络与深度学习》&am…