JavaScript之applye、bind和call方法详解
Question
-
Q1 apply()、bind()和call()方法的区别在哪?
-
Q2 apply()和call()的应用场景
-
Q3 apply()、bind()和call()方法手写实现逻辑
来源
继承自Function.prototype,属于实例方法
console.log(Function.prototype.hasOwnProperty('call')) //true
console.log(Function.prototype.hasOwnProperty('apply')) //true
console.log(Function.prototype.hasOwnProperty('bind')) //true
定义
apply()、bind()和call()方法的作用都是改变this指向,可以指定该函数内部this的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数。
一般用法
// 限浏览器Console执行
var year = 2022 // 不能用let
function getDate(month, day) {
console.log(this.year + '-' + month + '-' + day)
}
let obj = { year: 2023 }
getDate.call(this, 1, 1) //2022-1-1 this|null|undefined均可
getDate.call(obj, 1, 1) //2023-1-1
getDate.apply(obj, [1, 1]) //2023-1-1
getDate.bind(obj)(1, 1) //2023-1-1
区别
-
apply()的参数为数组
-
apply()和call()立即执行,bind()返回新函数,并非立即执行
apply()
找出最大值和最小值
var arr = [5, 6, 2, 3, 7]
console.log(Math.max.apply(null, arr))
console.log(Math.min.apply(null, arr))
将数组的空元素变为undefined
// 空元素与undefined的差别在于,数组的forEach方法会跳过空元素,但是不会跳过undefined和null。因此,遍历内部元素的时候,会得到不同的结果
console.log(Array.apply(null, [1, , 3])) // [1, undefined, 3]
转换类似数组的对象
function keith(a, b, c) {
return arguments
}
console.log(Array.prototype.slice.apply(keith(2, 3, 4))) //[2,3,4]
console.log(Array.prototype.slice.call(keith(2, 3, 4))) //[2,3,4]
bind()
var func = {
a: 1,
count: function () {
console.log(this.a++)
}
}
var ff = func.count.bind(func)
ff()
call()
调用对象的原生方法
var obj = {}
console.log(obj.hasOwnProperty('toString')) //false
obj.hasOwnProperty = function () {
return true
}
console.log(obj.hasOwnProperty('toString')) //true
console.log(Object.prototype.hasOwnProperty.call(obj, 'toString')) //false
调用父构造函数
function Product(name, price){
this.name = name
this.price = price
}
// 调用父构造函数的call方法来实现继承
function Food(name, price){
Product.call(this, name, price)
this.category = 'food'
}
function Toy(name, price){
Product.call(this, name, price)
this.category = 'toy'
}
var cheese = new Food('feta', 5)
var fun = new Toy('robot', 40)
console.log(cheese)
console.log(fun)
手写
apply()
/**
* 模拟 apply
* 调用一个具有给定 this 值的函数,以及以一个数组(或类数组对象)的形式提供的参数
* @param {object} ctx
* @param {} args
*/
Function.prototype.__apply = function (ctx, args) {
if (typeof this !== 'function') throw new TypeError('Error')
// 考虑 null 情况,参数默认赋值会无效
if (!ctx) ctx = window
// 将 this 函数保存在 ctx 上
ctx.fn = this
// 传参执行并保存返回值
const result = ctx.fn(...args)
// 删除 ctx 上的 fn
delete ctx.fn
return result
}
// ------------------------------ 测试 ------------------------------
const numbers = [5, 6, 2, 3, 7]
// Function.prototype.__apply()
console.log('Function.prototype.__apply()')
const max = Math.max.__apply(null, numbers)
console.log(max) // 7
// Function.prototype.apply()
console.log('Function.prototype.apply()')
const min = Math.min.apply(null, numbers)
console.log(min) // 2
bind()
/**
* 1. bind() 方法创建一个新的函数
* 2. 在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数
* 3. new 情况下忽略第一个参数
* 4. 其余参数将作为新函数的参数,供调用时使用
* @param {object} ctx
* @param {...any} args
* @returns {function} 返回一个原函数的拷贝,并拥有指定 this 值和初始参数
*/
Function.prototype.__bind = function (ctx, ...args) {
// 判断 this 是否为 function 类型
if (typeof this !== 'function') throw new TypeError('Error')
// 保存当前 this
const __this = this
return function F() {
return this instanceof F
? new __this(...args, ...arguments) // new
: __this.apply(ctx, [...args, ...arguments]) // 直接调用时绑定 this
}
}
// ------------------------------ 测试 ------------------------------
function print() {
console.log(this.name, ...arguments)
}
const obj = {
name: 'mxin',
}
// Function.prototype.__bind()
console.log('Function.prototype.__bind()')
// 直接调用,返回原函数拷贝,this 指向 obj
const F = print.__bind(obj, 26)
F(178) // mxin, 26, 178
// new 情况
const _obj = new F(145) // undefined, 26, 145
console.log(_obj) // print {}
// Function.prototype.bind()
console.log('Function.prototype.bind()')
const Fn = print.bind(obj, 26)
Fn(178) // mxin, 26, 178
const __obj = new Fn(145) // undefined, 26, 145
console.log(__obj) // print {}
call()
/**
* 模拟 call
* 使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数
* @param {object} ctx
* @param {...any} args
* @returns {any} 调用 this 的返回值,若无有返回值,则返回 undefined
*/
Function.prototype.__call = function (ctx, ...args) {
if (typeof this !== 'function') throw new TypeError('Error')
// 考虑 null 情况,参数默认赋值会无效
if (!ctx) ctx = window
// 将 this 函数保存在 ctx 上
ctx.fn = this
// 传参执行并保存返回值
const res = ctx.fn(...args)
// 删除 ctx 上的 fn
delete ctx.fn
return res
}
// ------------------------------ 测试 ------------------------------
function Product(name, price) {
this.name = name
this.price = price
}
// Function.prototype.__call()
console.log('Function.prototype.__call()')
function Food(name, price) {
Product.__call(this, name, price)
this.category = 'food'
}
const food = new Food('cheese', 5)
console.log(food)
// Food {name: "cheese", price: 5, category: "food"}
// category: "food"
// name: "cheese"
// price: 5
// __proto__:
// constructor: ƒ Food(name, price)
// __proto__: Object
// Function.prototype.call()
console.log('Function.prototype.call()')
function Toy(name, price) {
Product.call(this, name, price)
this.category = 'toy'
}
const toy = new Toy('car', 10)
console.log(toy)
// Toy {name: "car", price: 10, category: "toy"}
// category: "toy"
// name: "car"
// price: 10
// __proto__:
// constructor: ƒ Toy(name, price)
// __proto__: Object
本文由 mdnice 多平台发布
相关文章:
JavaScript之applye、bind和call方法详解
Question Q1 apply()、bind()和call()方法的区别在哪? Q2 apply()和call()的应用场景 Q3 apply()、bind()和call()方法手写实现逻辑 来源 继承自Function.prototype,属于实例方法 console.log(Function.prototype.hasOwnProperty(call)) //trueconsole.l…...
Docker,anaconda环境的部署与迁移
功能上线将提上日程,但是如何将我windows环境下的程序放到linux服务器的测试环境跑通呢?这是我这整个清明假期将要解决的一件事,最蠢的办法就是看自己的环境下有哪些依赖,如何到服务器上一个一个下,但是首先这个方法很…...
【大数据运维】Hbase shell 常见操作
文章目录 一. DDL1. 表的DDL1.1. 创建表1.2. 删除表 2. 列族的DDL2.1. 增加一个列簇2.2. 删除列族2.3. 修改列族版本(ing) 二. DML1. 插入与更新数据2. 删除数据3. 清空表 三. DQL1. scan:查一批数据1.1. 查询全部1.2. 过滤rowkey1.3. 过滤列…...
LeetCode-217存在重复的元素
217 存在重复的元素 给定一个整数数组,判断是否存在重复元素。 如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。 JavaScript的 Array 对象是用于构造数组的全局对象,数组是类似…...
基于两个单片机串行通信的电子密码锁设计
1.功能 电子号码锁在实际应用中应该有两部分,一部分在外部,有键盘部分和密码显示;另一部分内部,设置密码、显示密码。使用单片机自身带有的串口可以很方便的实现单片机之间的通信,使输入的密码值传送到主机检验是否是…...
产品经理功法修炼(3)之产品设计
点击下载《产品经理功法修炼(3)之产品设计》 1. 前言 产品经理的能力修炼并非局限于某一技能的速成,而是需要全面参与到产品的整个生命周期中,通过不断的实践来逐步提升自己的各项能力。尽管在企业的日常运作中,我们不可能身兼数职去扮演每一个角色,但作为产品的核心负…...
Qt 的发展历史、现状与启示
Qt 最早在1991年由挪威的两位程序员 Eirik Chambe-Eng 和 Haavard Nord 开发,他们在1994年创立 Trolltech 公司(奇趣科技)正式经营软件业务。Qt 的第一个公众预览版于1995年面世,之后在2008年被诺基亚收购;2011年到201…...
Quiet-STaR:让语言模型在“说话”前思考
大型语言模型(llm)已经变得越来越复杂,能够根据各种提示和问题生成人类质量的文本。但是他们的推理能力让仍然是个问题,与人类不同LLM经常在推理中涉及的隐含步骤中挣扎,这回导致输出可能在事实上不正确或缺乏逻辑。 考虑以下场景:正在阅读一…...
【Kotlin】匿名类和伴生类
1 匿名类 1)无继承 fun main() {var obj object {var name: String "zhang"override fun toString(): String {return name}}println(obj) // zhang } 2)有继承 fun main() {var obj object: People {var name: String "zhang"…...
【机器学习算法介绍】(3)决策树
决策树是一种常见的机器学习算法,用于分类和回归任务。它模拟了人类决策过程,通过一系列的问题来引导决策。决策树的构建涉及三个主要步骤:特征选择、树的构建和树的剪枝。 1. 特征选择 特征选择是决策树构建过程中的第一步,目的…...
算法之查找
1、顺序查找: package com.arithmetic.search; //顺序查找 //sequentialSearch 方法接收一个整数数组和一个目标元素作为参数,并使用顺序查找的方式在数组中查找目标元素。 //它通过循环遍历数组元素,逐个与目标元素比较,如果找到…...
LInux脚本学习
1.注释 #单行注释 以 # 字符开头就是单行注释 当然第一行除外,比较特殊 2.多行注释 3.Shell文件的作用 Shell文件就是linux命令集 4.sh脚本的执行方式 bash xxx.sh 5.新建的文件会没有执行权限 #为文件赋予执行权限 chmod ux xxx.sh 6.编写规范 #!/bin/bash #…...
JavaWeb基础(计网 socket 数据库 JDBC lombok Mybatis JUnit Maven)
本文用于检验学习效果,忘记知识就去文末的链接复习 1. 网络基础 1.1 计网基础 区分设备:IP地址 区分网络:网络地址 网络互联:路由器 主机上进程间通信:端口 http是常用的协议,基于TCP协议 TCP VS U…...
【HBase】
什么是HBase HBase是Google Bigtable的开源实现,类似Google Bigtable利用GFS作为其文件存储系统,HBase利用Hadoop HDFS作为其文件存储系统;Google运行MapReduce来处理Bigtable中的海量数据,HBase同样利用Hadoop MapReduce来处理HBase中的海量数据。 访问层次(数据…...
Vue3:使用Pinia存储、读取、修改数据
一、存储数据 Pinia插件中,存储数据的配置项是state count.ts import {defineStore} from piniaexport const useCountStore defineStore(count,{// 真正存储数据的地方state(){return {sum:6}} })loveTalk.ts import {defineStore} from piniaexport const use…...
基于 Quartz.NET 可视化任务调度平台 QuartzUI
一、简介 QuartzUI 是基于 Quartz.NET3.0 的定时任务 Web 可视化管理,Docker 打包开箱即用、内置 SQLite 持久化、语言无关、业务代码零污染、支持 RESTful 风格接口、傻瓜式配置、异常请求邮件通知等。 二、部署 QuartzUI 从 2022 年到现在没有提交记录…...
前端三剑客 —— CSS (第三节)
目录 上节回顾: 1.CSS使用有以下几种样式; 2.选择器 1.基本选择器 2.包含选择器 3.属性选择器 [] 4.伪类选择器 : 5.伪元素选择器 ::before :after 3.常见样式的使用 常见样式参考表 一些特殊样式 媒体查询 自定义字体 变换效果 translate&…...
C# 系统学习(异步编程)
在C#中,异步编程是一种优化程序性能的关键技术,特别是在处理I/O密集型操作(如网络请求、数据库查询、文件读写等)时,能够有效避免由于长时间等待而导致的线程阻塞,从而提高应用的响应速度和资源利用率。asy…...
前端工程师————CSS学习
选择器分类 选择器分为基础选择器和复合选择器 基础选择器包括:标签选择器,类选择器,id选择器,通配符选择器标签选择器 类选择器 语法:.类名{属性1: 属性值;} 类名可以随便起 多类名使用方式&am…...
C# 登录界面代码
背景 MVVM 是一种软件架构模式,用于创建用户界面。它将用户界面(View)、业务逻辑(ViewModel)和数据模型(Model)分离开来,以提高代码的可维护性和可测试性。 MainWindow 类是 View&a…...
点云的Python均值采样
一、代码 Python import numpy as np import open3d as o3ddef mean_sampling(point_cloud, num_samples=None, depth=None, method=knn, k=10):"""对点云进行均值下采样。:param point_cloud: Open3D PointCloud对象:param num_samples: (仅当method=knn时使…...
xss-labs 11-13通关记录
前言 最近复习xss知识,整理一下xss的绕过思路。 level11 观察测试: 1.四个隐藏参数标签 2.全部get传参一遍发现t_sort可赋值,使用的是get传参 3.针对t_sort测试过滤的字符 t_sort< > & ; " 检测到他除了<>,别的全部过滤。 因为…...
Unity类银河恶魔城学习记录12-2 p124 Character Stats UI源代码
Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_Statslot.cs using System.Collections; using System.Collections.Gen…...
技术揭秘:如何打造完美互动的充电桩硬件与服务平台?
充电桩平台全套源码地址 https://gitee.com/chouleng/cdzkjjh.git 这张图像是一个系统或服务的架构图。以下是对图中各个部分的描述: 前端: 位于图像的顶部,颜色为浅绿色。用户服务端: 紧邻前端,颜色为淡黄色。设备服…...
【Django学习笔记(四)】JavaScript 语言介绍
JavaScript 语言介绍 前言正文1、JavaScript 小案例2、代码位置2.1 在当前 HTML 文件中2.2 在其他 js 文件中 3、代码注释3.1 HTML的注释3.2 CSS的注释3.3 Javascript的注释 4、变量 & 输出4.1 字符串4.2 数组4.3 对象(python里的字典) 5、条件语句6、函数7、DOM7.1 根据 I…...
IO和NIO的主要区别在哪里?
Java 中的 IO(输入/输出)和 NIO(新输入/输出)都是处理输入和输出操作的方式,它们的主要区别在于如何处理数据的读写。 阻塞与非阻塞: IO是阻塞的,这意味着当一个线程调用read()或write()时,该线…...
爬虫部署平台crawlab使用说明
Crawlab 是一个基于 Go 语言的分布式网络爬虫管理平台,它支持 Python、Node.js、Jar、EXE 等多种类型的爬虫。 Crawlab 提供了一个可视化的界面,并且可以通过简单的配置来管理和监控爬虫程序。 以下是 Crawlab 的一些主要优点: 集中管理&am…...
uniapp uni.scss中使用@mixin混入,在文件引入@include 样式不生效 Error: Undefined mixin.(踩坑记录一)
问题: 在uni.scss文件定义mixin 2. 在vue文件引入: 3. 出现报错信息: 4. 问题思考: 是不是需要引入uni.scss ? 答案不需要 uni.scss是一个特殊文件,在代码中无需 import 这个文件即可在scss代码中使用这里的样式变量。uni-app的…...
Redis的5大常见数据类型的用法
上一篇文章我们讲了Redis的10大应用场景,这一篇文章就针对Redis的常用数据结构进行一个说明,通过示例的形式演示每一种数据结构如何使用。 当涉及Redis的数据操作时,不同数据类型对应的不同数据结构,如下就对5大常用的数据类型进行…...
刘小光本就疑心赵本山与他媳妇李琳有染,赵本山为证实清白便想起蛋糕上的字,结果呢?
刘小光本就疑心赵本山与他媳妇李琳有染,赵本山为证实清白便想起蛋糕上的字,结果呢? ——小品《生日快乐》(中5)的台词 (接上) 赵本山:噢!对对!那谁,老四,是…...
金坛网站建设哪家好/个人网站设计
关于推送的集成请参考这篇文章,本篇文章将引导你集成统计功能,只需要简单的三个步骤就可以集成统计功能。第一步 安装在你的项目路径下执行命令:npm install janalytics-react-native --savenpm install jcore-react-native --savereact-nati…...
网站开发环境是什么/独立站seo优化
一、关于版本控制 版本控制是一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统。我们通常仅对保存着软件源代码的文本文件做版本控制,但实际上,你可以对任何类型的文件进行版本控制。 采用版本控制系统(VCSÿ…...
网站建设需要个体营业执照吗/100个经典创意营销方案
1.默认浏览器打开网站 import process; process.execute("网址")打开网址 wb.go("网址") 2. WEB窗体最大化、最小化 //点击最大化,但是这个函数如果发现最大化会还原窗口,并返回一个值表示当前是否最大化winform.hitmax()//点击最小化按钮wi…...
遵义市住房城乡建设局网站/天津优化加盟
目录实验准备实验总结参考实验准备 准备两台笔记本电脑,两个USB转TTL(一个的 RX接另一个的TX,其它的可以不用接)。 实验 打开串口调试助手,选择好端口,打开图片文件并发送: 在另一台电脑上即…...
网页qq邮箱怎么发文件给别的邮箱/seo网站培训优化怎么做
(1)Javascript的变量命名需要注意的3点:1),变量以字母开头,中间可以出现数字或者下划线“_”字符。变量名不能有空格,“”,“-”,“,”等特殊字符。2…...
wordpress会员发布文章/上海公司排名
设置定时任务很简单,用Timer类就搞定了。一、延时执行首先,我们定义一个类,给它取个名字叫TimeTask,我们的定时任务,就在这个类的main函数里执行。代码如下:package test;import java.util.Timer;public cl…...