首页 > 编程语言 >JavaScript的apply、call、bind方法

JavaScript的apply、call、bind方法

时间:2023-12-29 23:34:57浏览次数:34  
标签:Product name 构造方法 Food price JavaScript call apply

JavaScript的apply、call、bind方法

概述

简述这三个方法存在一定的迷惑性 ,而且对于刚看ES6的人来说,十分难理解,这里为了以后我可能会复习到这个知识点,做出详解。总的来说,这三个方法都是将某某某(某01)绑定在某某某(某02)上,然后执行这个被绑定的某某某(某01),或者单纯就是绑定不执行。


详解

从前端必备网站 MDN 上我们可以得知以上三种方法的完全体。


Function.prototype.apply(thisArg , argsArray); //apply方法

Function.prototype.call(thisArg , ...args); //call方法

Function.prototype.bind(thisArg , ...args); //bind方法


然后我们来分别看看这三个方法的例子,首先是call,我把它放在第一个讲,因为我觉得它很有代表性。


Call方法

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  //这里调用了call方法
  Product.call(this, name, price);
  this.category = 'food';
}

console.log(new Food('cheese', 5).name);
// Expected output: "cheese"

第一眼看上去,这个方法到底是啥?怎么这么难理解?它到底做了什么?


解析

我们不考虑MDN对这个方法参数的专业解释,来用我们自己的语言描述这个方法。


下面给出我们在上面代码块中调用call方法的部分。

Product.call(this, name, price);

这句代码到底做了什么事情,首先我们从它的this入手,有这样一句话


构造函数中this指向对象实例


所以this指向的,就是function Food(...)构造方法的实例,call方法的第一个参数是谁我们就找到了。

接下来是call方法的第二个参数,注意call方法的完全体的第二个参数名字为 “argsArray” ,这个名字的意思是什么?参数数组,对了,所以 “name” 和 “price” 应该有一个统一的名称,参数数组中的参数。

现在我们解释了代码块中调用call方法部分的两个参数,那么,接下来的问题是call方法利用这两个参数做了什么事情呢?


我们再把call方法的完全体拿过来看一看。


Function.prototype.apply(thisArg , argsArray);


除去原型链(prototype)部分,这个方法写为 Function.apply(thisArg , argsArray);

Function,Function是谁?在代码块中调用call方法部分中,Function是Product,call方法会把参数传给Product。

注意,call方法一旦调用就立即执行对应的Function。


经过上面的讨论我们基本上分析完了,下面给出我们的通俗理解。


“我们将Product构造方法,绑定给了Food构造方法,并将Product构造方法的this指向Food构造方法的实例。也就是说我们执行Food构造方法时调用Product构造方法,这个调用是Product构造方法的内容在Food构造方法的内部调用


那这样说我直接在Food构造方法中调用Product构造方法就好了,为什么要用到call方法?

(这么问的话说明你还没有理解我上面的这段话,我给个例子)

我们把这句话翻译成代码。

function Food(name, price) {
  Product(name, price);
  this.category = 'food';
}

把我们的通俗理解翻译成代码如下

function Food(name, price) {
  //Product.call(this, name, price);和下面代码等价
  this.name = name;
  this.price = price;
  ...
}

看出区别了吗?两个代码块调用this的指向是不同的,Product(name, price);方法的this指向Product构造方法的实例,而后者代码块的this指向Food构造方法的实例。这样就使得console.log(new Food('cheese', 5).name);运行时,呈现两种完全不同的结果。


后者代码块的new Food('cheese', 5)运行时会将参数直接传给Product(name, price);然后呢?然后就没有了!Product(name, price);将参数传给了Product构造方法,而Product构造方法的this指向他自己的实例,赋值当然也会赋给它自己的实例。


这里附上Product构造方法的代码。

function Product(name, price) {
  this.name = name;//赋值
  this.price = price;//赋值
}

所以当运行new Food('cheese', 5).name时,返回的值是undefined,因为new Food('cheese', 5)产生的实例中,根本不含有name和price属性!


因此,想让name和price的值赋给Food构造方法的实例,必须改变Product构造方法中this的指向,让Product构造方法的this指向Food构造方法的实例才行。


call方法就为我们做了这件事,这也是call方法第一个参数的意义所在。


bind方法

const module = {
  x: 42,
  getX: function () {
    return this.x;
  },
};

const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// Expected output: undefined

const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// Expected output: 42

经过call方法的磨练,想必理解上述代码十分简单,但是要注意一件事情,即bind方法调用后,它对应的Function不会立即执行,要等我们去调用才执行。


apply方法

const numbers = [5, 6, 2, 3, 7];

const max = Math.max.apply(null, numbers);

console.log(max);
// Expected output: 7

const min = Math.min.apply(null, numbers);

console.log(min);
// Expected output: 2

这里也不给出具体的解析了,同理call方法即可。注意,apply方法调用后,它对应的Function会立即执行。

标签:Product,name,构造方法,Food,price,JavaScript,call,apply
From: https://www.cnblogs.com/sumuwen/p/17935853.html

相关文章

  • ECharts 是一个使用 JavaScript 实现的开源可视化库¹²³⁴。它可以流畅地运行在 PC
    ECharts是一个使用JavaScript实现的开源可视化库¹²³⁴。它可以流畅地运行在PC和移动设备上,兼容当前绝大部分浏览器(如IE8/9/10/11,Chrome,Firefox,Safari等)²³⁴。ECharts底层依赖轻量级的Canvas类库ZRender¹²³,提供直观,生动,可交互,可高度个性化定制的数据可视化图表¹......
  • JavaScript | Variable、Function、Module、Class (一)
    函数函数声明functionsayHello(){return"HelloJavaScript!!"}函数表达式letsayHello=function(){return"HelloJavaScript!!"}函数、变量提升:函数和变量都会被提升,且函数会被优先提升;提升的意思是只要有声明定义,那么先调用都可以。因为JS会把定义放到......
  • HTML学习第七天:JavaScript进阶与事件处理
    在今天的HTML学习中,我进一步深入了JavaScript的学习,特别是事件处理方面。早上,我回顾了昨天学习的JavaScript基础知识,并进行了一些练习,以加深自己的理解。然后,我开始学习事件处理。事件处理是JavaScript中非常重要的一部分,它允许我们响应用户的各种操作,如点击、滑动、键盘输入等。我......
  • HTML学习第六天:初步探索JavaScript与交互
    在今天的HTML学习中,我初步探索了JavaScript和网页交互的世界。早上,我首先了解了JavaScript的基本概念和语法。JavaScript是一种用于增强网页交互性的脚本语言,它可以直接在浏览器中运行。我学习了如何使用变量、函数和基本的控制结构来编写JavaScript代码。午后,我开始将JavaScript与......
  • Javascript 原型链 jQuery原型链 js原型链 我感觉我能一直写下去 扶着我>_<
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>原型链闭环</title><scriptsrc="./jquery.js"></script></head><body><divclass=&quo......
  • k8s 安装kubesphere3.4.1 多次安装报错 Error from server (InternalError): Internal
    failed:[localhost](item={'ns':'kubesphere-system','kind':'users.iam.kubesphere.io','resource':'admin','release':'ks-core'})=>{"ansible_loop_var":"......
  • JavaScript事件
    事件JavaScript事件,就是用户或浏览器本身的某种行为,一般是用户对页面的一些动作引起的,比如用户的点击某个链接、在文本框中输入文本等。绑定对应的事件方法一:直接在元素上面添加一个事件属性语法:方法二:在js中找到dom添加事件语法:方法三:使用addEventListener 语法:注意......
  • rust call sqlite3 error: linking with `link.exe` failed: exit code: 1181
    rustcallsqlite3error:linkingwithlink.exefailed:exitcode:1181声明:本文禁止csdn.net及所有所有子网站转载。禁止以营利性为目的的转载。报错error:linkingwith`link.exe`failed:exitcode:1181......
  • 创建一个双模式跨运行时的 JavaScript 包
    本文将指导你发布双模式、跨运行时的JavaScript包。了解如何创建与ESM和CommonJS以及Node.js、Deno和浏览器等不同运行时兼容的库。随着JavaScript开发的不断发展,人们越来越需要能在多种环境中运行的强大依赖包。在本文中,我们将探讨如何发布跨运行时、双模式的JavaScr......
  • Thoughts and ideas about how to apply LLMs in specific domains like clinic/law/f
    ApplyingLLMsinSpecificDomainsAsauniversitystudentwhohasjustcompletedfine-tuningTinyLLaMA-1bwithclinicalinstructiondatausingtheQLoRAmethodandevaluateditontheMedMCQAdataset,Ihavegatheredsomeinsightsandideasonhowtoappl......