JS面试中你不知道的call apply bind方法及使用场景详解

目录
  • 面试
  • 三者区别
    • call
    • apply.
    • bind
  • 总结
    • 应用场景
  • 简单实现
    • call
    • apply
    • bind

面试

面试官 :说一下 call apply bind 的三者区别吧?

我:啊.....这。

三者区别

call

我们先来看看 call call 函数接收两个参数

@params1 需要指向this

@params2 需要携带的参数

就拿这段代码 来说 我调用 foo 函数 的时候 想去 执行obj 中的 eat函数 怎么办?

默认 我的 foo 里面什么页面有 怎么可能会打印 吃饭呢?this默认指向 window ,window 对象中 没有 eat 方法不应该 报错 not defind 吗?

let obj = {
  eat: function (args) {
    console.log("吃饭", args);
  }
}
function foo(...args) {
  this.eat(args)
}

你可以这样 , 此时调用的时候 foo 的函数 this 就指向了 obj 但是只是这一次调用哦 ,下次 this 是指向 window

console.log(foo.call(obj, 123, 456)); / / 吃饭 [ 123, 456 ]

调用结果 : 传入 this 和 参数 立即执行函数

apply.

@params1 需要指向this

@params2 需要携带的参数 传入的参数数据类型为 Array

let obj = {
  eat: function (args) {
    console.log("吃饭", args);
  }
}
function foo(...args) {
  this.eat(args)
}
console.log(foo.apply(obj, [1, 2, 3])); // 吃饭 [1,2,3 ]

调用结果 : 传入 this 和 参数,立即执行

bind

@params1 需要指向this

@params2 需要携带的参数

let obj = {
  eat: function (args) {
    console.log("吃饭", args);
  }
}
function foo(...args) {
  this.eat(args)
}
console.log(foo.bind(obj, 1, 2, 3)()); //吃饭 [ 1, 2, 3 ]

调用结果 : 传入 this 和 参数 返回一个 新的函数,不会立即执行

总结

call 函数 传入绑定 this的对象 ,携第二个参数以 参数列表形式传入 并会立即执行

apply 函数 传入绑定 this的对象 第二个参数以 数组的形式 传入 并会立即执行

bind 函数 传入绑定 this的对象 第二个参数以 数组或参数列表的形式传入 不会立即执行函数会返回一个新的函数 自由调用

应用场景

利用call 实现 构造函数原型继承

function Person(name, age, friends) {
  this.friends = friends
  this.name = name
  this.age = age
}
Person.prototype.eat = function () {
  console.log(`${this.name}在吃饭`);
}
Person.prototype.running = function () {
  console.log(`${this.name}去跑步了`);
}
function Student(study, name, age, friedns) {
  Person.call(this, name, age, friedns)
  this.study = study
}
function Teacher(plaseLoveStudent) {
  this.plaseLoveStudent = plaseLoveStudent
}
//继承 person
Student.prototype = new Person()
const stu = new Student('语文', "张三", 18, ['王安石'])
const stu2 = new Student('数学', "李四", 18, ['哈利波特'])
const tec = new Teacher("王安怡")
console.log(stu === stu2);
console.log(stu);
console.log(stu.friends);
console.log(stu2.friends);

简单实现

call

实现思路 :

1:在Function 原型身上添加一个方法。

2:mycall 接受 两个参数 一个是绑定的 this,还有就是 参数列表

3:保存调用者,其实这里更严谨一点还需要判断调用者的 类型

4:判断传入的thisArgs 是不是 undefined 或者 null 如果是 则 this指向 window 否则将 绑定的 this封装成 一个对象

5:然后将 函数本身保存在 上面封装好的对象中

6:调用并传入args

7:完成实现 this指向的改变

Function.prototype.mycall = function (thisArgs, ...args) {
  /**
   *
   * 保存this(当前调用者)
   *
   */
  const newFunc = this
  // 在当前调用者 this身上 保存 调用者
  thisArgs = (thisArgs !== undefined && thisArgs !== null) ? Object(thisArgs) : window
  thisArgs.func = newFunc
  thisArgs.func(...args)
}

apply

apply 就不说了 实现思路是一样的 只不过传入的参数不一样做一个判断就行了

Function.prototype.myapply = function (thisArgs, argArray) {
  if (!(argArray instanceof Array)) {
    throw '参数类型限定为 Array'
  }
  else {
    const func = this
    thisArgs = (thisArgs !== undefined && thisArgs !== null) ? Object(thisArgs) : window
    thisArgs.fn = func
    thisArgs.fn(argArray)
  }
}

bind

bind 跟 apply call 有一些区别

bind 会返回一个新的函数 , 所以我们在内部需要自己定义一个 函数 给返回出去, 并且,可能出现 返回新函数调用时 继续传入参数 所以我们需要将参数合并

Function.prototype.mybind = function (thisArgs, ...argArray) {
  const oldFunc = this
  console.log(this);
  thisArgs = (thisArgs !== undefined && thisArgs !== null) ? Object(thisArgs) : window
  function proxyFn(...args) {
    thisArgs.func = oldFunc
    const funcCallResult = thisArgs.func([...argArray, ...args]) // 合并两次的 参数
    delete thisArgs.func
    return funcCallResult
  }
  return proxyFn
}

谢谢,到此就完成了简单版的 call apply bind 的实现,更多关于JS call apply bind方法的资料请关注我们其它相关文章!

(0)

相关推荐

  • JavaScript手写call,apply,bind方法

    目录 前言 改写this实现思路 前期准备 手写call方法 手写apply方法 手写bind方法 前言 改变this指向在书写业务的时候经常遇到,我们经常采用以下方法进行改写 使用作用声明变量存储this 使用jJavaScript的原生方法call,apply,以及bind进行改写 第一种方法就不说了,就是一个变量存储的问题,主要说第二种如何实现的 call,bind,apply方法都是JavaScript原生的方法,挂载在Function原型上,使得所有函数都可以调用,今天我们来实现一下c

  • 一文搞懂JavaScript中bind,apply,call的实现

    目录 bind.call和apply的用法 bind call&apply 实现bind 实现call和apply 总结 bind.call和apply都是Function原型链上面的方法,因此不管是使用function声明的函数,还是箭头函数都可以直接调用.这三个函数在使用时都可以改变this指向,本文就带你看看如何实现bind.call和apply. bind.call和apply的用法 bind bind()方法可以被函数对象调用,并返回一个新创建的函数. 语法: function.bin

  • JS 函数的 call、apply 及 bind 超详细方法

    目录 JS 函数的 call.apply 及 bind 方法 一.call() 方法 1.call()方法的模拟实现 二.apply() 方法 1.apply()方法的模拟实现 三.bind() 方法 1.bind() 方法的模拟实现 四.总结 JS 函数的 call.apply 及 bind 方法 一.call() 方法 调用 call() 方法会立即执行目标函数,同时改变函数内部 this 的指向.this 指向由方法的第一个参数决定,后面逐个列举的任意个参数将作为目标函数的参数一一对应传入

  • 使用JS简单实现apply、call和bind方法的实例代码

    目录 1.方法介绍 2.apply.call和bind方法的实现 2.1.apply的实现 2.2.call的实现 2.3.bind的实现 总结 1.方法介绍 apply.call和bind都是系统提供给我们的内置方法,每个函数都可以使用这三种方法,是因为apply.call和bind都实现在了Function的原型上(Function.prototype),而他们的作用都是给我们函数调用时显式绑定上this.下面先介绍一下它们的基本用法: apply方法:调用一个具有给定this值的函数,以及

  • JavaScript函数之call、apply以及bind方法案例详解

    总结 1.相同点 都能够改变目标函数执行时内部 this 的指向 方法的第一个参数用于指定函数执行时内部的 this 值 支持向目标函数传递任意个参数 若不向方法的第一个参数传值或者传递 undefined.null,则在 JavaScript 正常模式下,目标函数内部的 this 指向 window 对象,严格模式下,分别指向 undefined.null. 2.区别 apply() 方法可接收两个参数,而 call() 和 bind() 方法则可接收多个参数. apply() 方法向目标函数

  • JS面试中你不知道的call apply bind方法及使用场景详解

    目录 面试 三者区别 call apply. bind 总结 应用场景 简单实现 call apply bind 面试 面试官 :说一下 call apply bind 的三者区别吧? 我:啊.....这. 三者区别 call 我们先来看看 call call 函数接收两个参数 @params1 需要指向this @params2 需要携带的参数 就拿这段代码 来说 我调用 foo 函数 的时候 想去 执行obj 中的 eat函数 怎么办? 默认 我的 foo 里面什么页面有 怎么可能会打印 吃

  • jQuery中的on与bind绑定事件区别实例详解

    on(events,[selector],[data],fn) events:一个或多个用空格分隔的事件类型和可选的命名空间,如"click"或"keydown.myPlugin" . selector:一个选择器字符串用于过滤器的触发事件的选择器元素的后代. data:当一个事件被触发时要传递event.data给事件处理函数. fn:该事件被触发时执行的函数. false 值也可以做一个函数的简写,返回false. bind(type,[data],fn) 为每

  • Vue中插槽slot的使用方法与应用场景详析

    什么是插槽? 我们知道在Vue中 Child 组件的标签 的中间是不可以包着什么的 . 可是往往在很多时候我们在使用组件的时候总想在组件间外面自定义一些标签,vue新增了一种插槽机制,叫做作用域插槽.要求的版本是2.1.0+: 插槽,其实就相当于占位符.它在组件中给你的HTML模板占了一个位置,让你来传入一些东西.插槽又分为 匿名插槽.具名插槽.作用域插槽. 在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令).它取代了 slot 和 slot-sc

  • Angular.js项目中使用gulp实现自动化构建以及压缩打包详解

    gulp介绍 基于流的前端自动化构建工具,利用gulp可以提高前端开发效率,特别是在前后端分离的项目中.使用gulp能完成以下任务: 压缩html.css和js 编译less或sass等 压缩图片 启动本地静态服务器 其他 目标 一键安装项目所有的依赖模块 一键安装项目所有的依赖库 代码检查确保严格语法正确 能将angularjs的html装换成js模块并且压缩到js文件中 将所有css文件合并压缩 将所有的js文件合并压缩 动态引入资源文件 拥有开发环境和生产环境两种打包方式 工具 npm基于

  • String中intern方法的使用场景详解

    在讲intern方法前,我们先简单回顾下Java中常量池的分类. 常量池的分类# Java中常量池可以分为Class常量池.运行时常量池和字符串常量池. 1. Class文件常量池 在Class文件中除了有类的版本.字段.方法.接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用. 所谓字面量类似与我们平常说的常量,主要包括以下两种 文本字符串,例如String a = "aa".其中"aa"就是

  • Python装饰器实现方法及应用场景详解

    应用场景: 1.授权(Authorization) 装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint).它们被大量使用于Flask和Django web框架中.这里是一个例子来使用基于装饰器的授权: from functools import wraps # 最新版python引用是 import functools def requires_auth(f): # f 就是我们需要装饰的函数,一看就是不带参数的装饰器 @wraps(f) # 新版python写法 @

  • jquery中live()方法和bind()方法区别分析

    本文实例讲述了jquery中live()方法和bind()方法区别.分享给大家供大家参考,具体如下: live()不受加载时间顺序的影响,只要查找能够配对上就能够绑定对应的事件,而bind方法只有在第一次被加载的时候才绑定时间,如果代码之后再加载配对的元素,则不能绑定对应的事件 $("#manual_disconnect").live("click", function(){ connectionProfile("0"); }); $("

  • 在JS循环中使用async/await的方法

    async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案.目前,async / await这个特性已经是stage 3的建议,可以看看TC39的进度,本篇文章将分享在JS循环中使用async/await的方法. 在开发maty.js时,遇到一个数组任务,数组项是内部异步执行的函数,期望是同步依次执行每项函数,每项函数执行完本身的异步任务后,继续下一项. 刚开始单纯使用map来循环执行,并且await每项函数.如下所示: starters.map(async (fn,

  • JS中script标签defer和async属性的区别详解

    向html页面中插入javascript代码的主要方法就是通过script标签.其中包括两种形式,第一种直接在script标签之间插入js代码,第二种即是通过src属性引入外部js文件.由于解释器在解析执行js代码期间会阻塞页面其余部分的渲染,对于存在大量js代码的页面来说会导致浏览器出现长时间的空白和延迟,为了避免这个问题,建议把全部的js引用放在</body>标签之前. script标签存在两个属性,defer和async,因此script标签的使用分为三种情况: 1.<script

随机推荐