【代码片段】call、apply、bind

LilyLucyHello

const lily= {
  name: 'Lily',
  sayHello(helloWord, other){
    console.log(`${this.name} say ${helloWord} to ${other}`)
  }
}
lily.sayHello("hello", "Lucy")
// Lily say Hello to Lucy

那换做其他对象怎么复用sayHello方法呢

const jack = {
    name:'Jack'
}
lily.sayHello.call(jack, 'hello', 'Lilei')
// Jack say Hello to Lilei

lily.sayHello.apply(jack,[ 'hello', 'Lilei'])
// Jack say Hello to Lilei

let say2 = lily.sayHello.bind(jack,'hello')
say2('Lilei')
// Jack say Hello to Lilei
say2('David')
// Jack say Hello to David

下面实现callapplybind的方法

Function.prototype.myCall = function(target,...args){
  target = target || window
//定义一个不会重复的key,作为目标对象target的属性key
  const funKey= Symbol()  
 //this即被调用的函数或对象,将this变成目标对象target属性key的属性值
  target[funKey] = this 
  const res = target[funKey](...args) 
  delete target[funKey] // 执行完借用的函数后,删除掉
  return res
}

 // 区别就是这里第二个参数直接就是个数组
Function.prototype.myApply = function(target,args){
  target = target || window
  const funKey= Symbol()
  target[funKey] = this
  const res = target[funKey](...args) 
  delete target[funKey]
  return res
}

// bind返回的是个函数,需要执行
Function.prototype.myBind = function (target,...outArgs) {
  target = target || {} 
  const funKey = Symbol()
  target[funKey] = this
  return function (...innerArgs) { // 返回一个函数
    const res = target[funKey](...outArgs, ...innerArgs) 
    //不能删除,闭包函数(偏函数)
    // delete target[funKey] 
    return res
  } 
}

从上面的myBind的实现看;bind涉及到闭包,下面说下闭包、偏函数、柯里化

转自: JS闭包应用-私有变量、柯里化、偏函数@ Peterer~王勇

什么是闭包?

function generate() {
  const a = 1;
  //注意需要return内部函数,才回形成闭包
  return function () {
    // a这个变量不在当前作用域,于是它是一个自由变量。
    // 引用了自由变量的函数称为闭包。
    console.log(a++);
  };
}

generate作为高阶函数返回了一个新的函数,该函数引用了外部作用域中的变量a,于是该函数称为闭包函数。

  • 闭包就是:引用了自由变量的函数。
  • 自由变量:指在当前作用域引用但既没有定义在当前作用域也未定义在全局作用域,而是定义在外层的局部作用域中的变量。

所以在此明确几个关于闭包的要点:

  • 闭包必然是定义在一个函数内部的,因为局部作用域只存于函数内。
  • 局部作用域的变量无法直接从外部访问,只能通过作用域链访问,所以闭包是访问局部变量的桥梁。
  • 闭包造成的直接结果是自由变量不被垃圾回收,所以自由变量可以缓存一些信息。

闭包的典型应用场景有两个:

  • 设置私有变量(基于局部变量的不可访问性)
  • 柯里化和偏函数(基于自由变量的不回收性)

私有变量就是那些函数可以调用但是外部无法直接获取的变量。比如下面这个场景:

function User() {
  // 这里的_password承担着私有变量的作用
  let _password;
 
  return class User {
    constructor(username, password) {
      this.username = username;
      // 使用自由变量保存密码
      _password = password;
    }
 
    login() {
      console.log(this.username, _password);
    }
  };
}
 
const user = new (User())("diana", "password");
 
user.login();
  • 我们希望隐藏用户的密码,只允许内部访问,此时就可以使用自由变量作为“私有变量”,返回一个闭包进行访问。
  • 局部变量的外部不可访问性是关键,本质上这一切都来自于JS使用的词法作用域模型,变量只能从内向外单向查找。

柯里化是一种操作技巧,在编程中指的是:将接受n个参数的单个函数转换为接受单个参数的n个函数。比如下面这个场景:

function info(country, province, city) {
  console.log(country + "-" + province + "-" + city);
}

我们想要打印城市信息,对于某个省的城市我们需要重复的输入country,province这两个字段,此时我们可以对该函数进行柯里化改造:

function info(country) {
  return function (province) {
    return function (city) {
      console.log(country + "-" + province + "-" + city);
    };
  };
}
const province = info("中国")("浙江省");
province("杭州市");
province("温州市");
  • 我们将接受三个参数country,province,city的函数转换为三个只接受单个参数的函数,然后根据需要随时生成一个已经内置”部分参数“的函数。
  • 这么做最大的好处是提高了代码的复用性,我们可以提前缓存一些参数,避免重复输入。

偏函数也是一种操作技巧,在编程中指的是:将接受n个参数的单个函数任意固定a个参数,返回接受剩余n-a个参数的函数。

偏函数和柯里化属于一类操作,区别在于:

  • 柯里化强调函数只能接受“单参数”,有n个参数就要拆解为n个单参数函数;
  • 偏函数更加“随意”,将接受n个参数的函数一分为二,任意固定一个或多个参数。

上面的例子如果使用偏函数:

function info(country) {
  return function (province, city) {
    console.log(country + "-" + province + "-" + city);
  };
}
 
info("中国")("浙江省", "杭州市");
info("中国")("浙江省", "温州市");

柯里化和偏函数本质没什么区别,只是约束不同。能够实现这类操作的核心有两点:

  • 在于“自由变量”的不回收性,由于垃圾回收不去销毁闭包中引用的自由变量,我们才能缓存部分参数;
  • 在于JS使用静态的词法作用域,词法作用域的划分和查询根据”代码书写“的位置来决定。

对this对象的理解

作者:CUGGZ
链接:https://juejin.cn/post/6941194115392634888
来源:稀土掘金

this 是执行上下文中的一个属性,它指向最后一次调用这个方法的对象。在实际开发中,this 的指向可以通过四种调用模式来判断。

  • 第一种是函数调用模式,当一个函数不是一个对象的属性时,直接作为函数来调用时,this 指向全局对象。
  • 第二种是方法调用模式,如果一个函数作为一个对象的方法来调用时,this 指向这个对象。
  • 第三种是构造器调用模式,如果一个函数用 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对象。
  • 第四种是 apply 、 call 和 bind 调用模式,这三个方法都可以显示的指定调用函数的 this 指向。其中 apply 方法接收两个参数:一个是 this 绑定的对象,一个是参数数组。call 方法接收的参数,第一个是 this 绑定的对象,后面的其余参数是传入函数执行的参数。也就是说,在使用 call() 方法时,传递给函数的参数必须逐个列举出来。bind 方法通过传入一个对象,返回一个 this 绑定了传入对象的新函数。这个函数的 this 指向除了使用 new 时会被改变,其他情况下都不会改变。

这四种方式,使用构造器调用模式的优先级最高,然后是 apply、call 和 bind 调用模式,然后是方法调用模式,然后是函数调用模式。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,137评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,824评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,465评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,131评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,140评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,895评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,535评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,435评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,952评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,081评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,210评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,896评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,552评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,089评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,198评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,531评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,209评论 2 357

推荐阅读更多精彩内容