箭头函数的this指向谁_高阶函数

802162e86d3d25c04d2abfc3a4e0ff69.png

NodeJS 系列文章,本篇是第一篇,首先,预计将后续高频使用逻辑串一遍,依次是高阶函数,promise以及事件机制。本篇主要是高阶函数。

call、bind、apply

  • call、apply 都是改变 this 指向,区别是接受参数的方式不一样,call 一个一个传参数,apply 接收一个数组。
  • bind 会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind 方第一个参数作为 this,传入 bind 的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。
  • 当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法,bind 是返回的函数。
  • apply、call 则会立即执行函数。

this 指向

this 指向问题,谁调用,我就指向谁。

全局上下文

非严格模式和严格模式中this都是指向顶层对象(浏览器中是window)。

console.log(this === window); // true'use strict'console.log(this === window); // truethis.name = 'Hiraku';console.log(this.name); // Hiraku

函数上下文

普通函数调用模式

var name = '骁妈';var func = function() {console.log(this === window, this.name); // true 骁妈(浏览器)}; func();

在 ES5 中,全局变量是挂载在顶层对象(浏览器是 window )中。

const name1 = 'mahongqin';const func1 = function() {console.log(this === window, this.name1); // true undefined};const func2 = () => {console.log(this === window, this.name1); // true undefined};func1();func2();

let 没有给顶层对象中(浏览器是 window )添加属性,window.name1 和 window.func1,window.func2 都是 undefined。

严格模式中,普通函数中的 this 则表现不同,表现为 undefined。

'use strict';var name2 = '骁妈';var func3 = function() {console.log(this === window); // false}; func3();

call,apply 作用之一就是改变函数的 this 指向为第一个参数。 如果第一个参数是 undefined 或者 null,非严格模式下,是指向 window。严格模式下,就是指向第一个参数。

对象中的函数(方法)调用模式

var name3 = 'Hiraku_Ma';var func4 = function() {console.log(this, this.name);}var obj = {name: 'mhq',func: func4,attr: {name: 'mhq-gs',func: func4,}}obj.func(); // Object{} obj 'mhq'obj.attr.func(); // Object{} obj.attr 'mhq-gs'// 用call类比则为:obj.func.call(obj); // 'mhq'// 用call类比则为:obj.attr.func.call(obj.attr); // 'mhq-gs'

函数赋值之后变成普通函数。

构造函数调用模式

function Example(type){this.type = type;console.log(this);// return this;
}
var exp = new Example('mhq');

使用 new 操作符调用函数,会自动执行以下步骤:

  • 创建了一个全新的对象。
  • 这个对象会被执行[[Prototype]](也就是proto)链接。
  • 生成的新对象会绑定到函数调用的 this。
  • 通过 new 创建的每个对象将最终被[[Prototype]]链接到这个函数的 prototype 对象上。
  • 如果函数没有返回对象类型 Object( 包含 Functoin, Array, Date, RegExg, Error ),那么 new 表达式中的函数调用会自动返回这个新的对象。

new 操作符调用时,this 指向生成的新对象。 new 调用时的返回值,如果没有显式返回对象或者函数,才是返回生成的新对象。

function Example(type){this.type = type;console.log(this);return {};}var exp = new Example('mhq'); // { name: mhq }console.log(exp);// 如果返回函数 f ,则 exp 是函数 f,如果是对象 {} ,则 exp 是对象 {}

原型链中的调用模式

function Example(type){this.type = type;console.log(this);}Example.prototype.func = function() {console.log(this.type);};var exp = new Example('mhq');exp.func();

箭头函数调用模式

var name = 'mhq';var student = {name: 'hiraku',func: function () {var arrowFunc = () => {console.log(this.name);}arrowFunc();},arrowFunc2: () => {console.log(this.name);}}student.func(); // 'hiraku'student.arrowFunc2(); // 'mhq'
  • 语法更加简洁、清晰
  • 箭头函数不会创建自己的 this
  • 箭头函数的 this 指向定义时所在的外层第一个普通函数,跟使用位置没有关系
  • 被继承的普通函数的 this 指向改变,箭头函数的 this 指向会跟着改变
  • 箭头函数外层没有普通函数,严格模式和非严格模式下它的 this 都会指向 window (全局对象)
  • call()、apply()、bind() 无法改变箭头函数中 this 的指向
  • 箭头函数不能作为构造函数使用
  • 箭头函数没有自己的 arguments
  • 箭头函数的 this 指向全局,使用 arguments 会报未声明的错误
  • 箭头函数的 this 指向普通函数时,它的 arguments 继承于该普通函数
  • rest参数(...扩展符)取参数
  • 箭头函数没有原型 prototype
  • 箭头函数不能用作 Generator 函数,不能使用 yeild 关键字
var obj = {name: 'mhq',func: function () {console.log(this.name);return () => {console.log('arrowFn:', this.name);}}}var obj1 = {name: 'hiraku',}obj.func().call(obj1); // 'mhq'  'arrowFn:' 'mhq'obj.func.call(obj1)(); // 'hiraku' 'arrowFn:' 'hiraku'

DOM 事件处理函数调用

  • onclick 和 addEventerListener 是指向绑定事件的元素。
  • 一些浏览器,比如 IE6~IE8 下使用 attachEvent,this 指向是 window。

高阶函数(Higher-order function)

什么是高阶函数?高阶函数至少满足两个条件:接受一个或多个函数作为输入,输出一个函数。也可以这样理解,一个函数的参数是一个函数(回调函数);一个函数返回一个函数(函数柯里化)。

我们写代码时不希望破坏原有逻辑,所以将原有逻辑包上一个函数,这个函数内部实现自己的逻辑,即切片编程。

const originFunc = (...args) => {console.log('原函数', args);};// 希望在调用 originFunc 之前做一些事情,使用 Function.prototype 给每个函数扩展一些功能Function.prototype.before = function(cb) {return (...args) => {cb();this(...args);};};let newFunc = originFunc.before(() => {console.log('before originFunc');});newFunc('a', 'b', 'c');

一个异步并发问题

我同时发送多个请求,希望拿到最终的结果

function after(time, fn) {return () => {if (--time === 0) {fn();}};}const exaFun = after(3, () => {console.log('执行');});exaFun();exaFun();exaFun();

示例:

const fs = require('fs');const path = require('path');function run(times, fn) {const renderObj = {};return (key, value) => {renderObj[key] = value;console.log(key, value);if(--times === 0) fn(renderObj);};}let out = run(2, (result) => {console.log(result);});fs.readFile(path.resolve(__dirname, '1.txt'), 'utf8', (_, data) => {console.log(data, 'ddd')out('1', data);});fs.readFile(path.resolve(__dirname, '2.txt'), 'utf8', (_, data) => {out('2', data);});

函数柯里化

柯里化,即 Currying,为了给多参数函数提供了一个递归降解的方式,把提供多个参数的函数变换成接受一个单一参数的函数,并且返回余下参数而且返回结果的新函数。

const curring = (fn, arr = []) => {// 长度值的是参数个数let len = fn.length;return (...arg) => {arr = [...arr, ...arg];if (arr.length < len) return curring(fn, arr);return fn(...arr);};};const add = (a, b, c, d, e, f, g, h) => {return a + b + c + d + e + f + g + h;}console.log(curring1(add, [1, 2])(3, 4)(5)(6)(7, 8)) // 15

函数柯里化使用场景: 参数复用 延迟执行 预加载 动态创建函数

发布订阅、观察者模式

观察者模式 定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新 属于行为型模式,行为型模式关注的是对象之间的通讯 * 观察者和被观察者之间的通讯

const fs = require('fs');const e = {arr: [],on(fn) {this.arr.push(fn);},emit() {this.arr.forEach(fn => fn());}};e.on(() => {console.log('读取到了数据');})const renderObj = {};e.on(() => {if (Object.keys(renderObj).length === 2) {console.log('都读取完毕了');}});fs.readFile('./name.txt', 'utf8', (_, data) => {renderObj['name'] = data;e.emit();});fs.readFile('./age.txt', 'utf8', (_, data) => {renderObj['age'] = data;e.emit();});

发布订阅 就是事先存储好,稍后发布的时候让事先订阅的事执行 发布者并不会直接通知订阅者,换句话说,发布者和订阅者,彼此互不相识 * 在发布者和订阅者之间存在第三个组件,称为调度中心或事件通道,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地分发它们给订阅者

class Subject { // 被观察者constructor(name) {this.name = name;this.arr = [];this.state = '我很开心';}attach(observer) { // 注册观察者 基于发布订阅this.arr.push(observer);}setState(newState) {this.state = newState;this.arr.forEach(o => o.update(this)); // 通知所有观察者 我的状态发生了变化}}class Observer { // 观察者constructor(name) {this.name = name;}update(s) {console.log(s.name + '当前状态是' + s.state + '对:' + this.name);}}let s = new Subject('小宝宝');let o1 = new Observer('我');let o2 = new Observer('我媳妇');s.attach(o1);s.attach(o2);console.log(s.state);s.setState('不开心了');

本篇文章涉及到的高阶函数使用有函数柯里化、发布订阅|观察者模式等。下篇将分享 Promise 源码,手写 Promise。

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

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

相关文章

php怎么加编码,php怎么设置编码格式

php设置编码格式的方法&#xff1a;首先在php脚本中添加【header(“Content-Type: text/html; charsetutf-8")】&#xff1b;然后在静态页面设置编码&#xff1b;最后保证所有文件的编码相同即可。如果要使用gb2312编码&#xff0c;那么php要输出头&#xff1a;(推荐教程&…

java 中文 音序,java 中文字符串数组按照音序排列

java 中文字符串数组按照音序排列复制代码 代码如下:public class SortComparator implements Comparator{public int compare(Object o1,Object o2) {try{byte[] buf1 ((String) o1).getBytes("unicode");byte[] buf2 ((String) o2).getBytes("unicode"…

动感灯箱制作流程培训_广告立体灯箱的特点有哪些?

随着广告业的发展&#xff0c;灯箱广告行业也在突飞猛进。在灯箱广告屏的设计与制作中&#xff0c;为了追求真实感和艺术性&#xff0c;采用彩印或摄影喷绘;也有人用特种纸、塑料板(膜)、灯箱布等进行丝网印刷制作灯箱图片&#xff0c;并根据成本和耐候性要求选择制作方法和灯箱…

supervisor 重启_supervisor_twiddler的使用

点击上方蓝字关注【 北邮郭大宝 】Supervisor可以很好的实现Python的进程管理&#xff0c;但是新增进程时需要配置文件&#xff0c;对于需要动态创建进程的场景不是很友好&#xff0c;supervisor_twiddler插件可以帮助实现上述功能。本文就supervisor_twiddler的使用做简单的de…

matlab的词云,Word Cloud (词云) - JavaScript

在上一篇中已经分享了用 Python 创建词云了。接下来继续总结其他创建词云的方法。&带道术用量确示常构端析以要效开的用&#xff0c;近不gt;> Create Word Cloud via JavaScrip要圈器是天的年编功小还久概据含直这请框结业未商屏页屏随会维气大机域页效实一应控高标tJav…

unique函数_unique函数使用场景(一)

unique函数使用场景(一)前情提示&#xff1a;Microsoft 365(就是原来的office 365)已经推出有一段时间了&#xff0c;去年年审就在项目上使用365更新的一系列动态函数来提高审计效率(大胆一点&#xff0c;就是更好的偷懒)。讲解动态函数的文章不多&#xff0c;且365普及度低&am…

c++gdal如何在大图像中截取小图像并获取其图像信息_【图像处理】OpenCV系列十 --- 边缘检测之Canny算子...

上一篇我们学习了图像处理形态学相关知识点&#xff0c;相信大家学习之后已经对形态学有了足够的理解了&#xff0c;那么接下来&#xff0c;我们一起来学习一下图像处理中的边缘检测吧&#xff01;我们将会重点学习边缘检测各种算子和滤波器 --- Canny算子,Sobel算子,Laplace算…

笔记本屏幕30hz_你真的了解笔记本电池和电源适配器吗?

很多笔记本硬件配置相似&#xff0c;但续航或性能却相差一大截。实际上&#xff0c;笔记本的续航能力在很大程度上取决于电池&#xff1b;而实际性能&#xff0c;则还会受到电源适配器功率的影响。想认识这两个硬件&#xff0c;就需要从它们的基本参数谈起。笔记本电池笔记本的…

java 俄文,俄文字体在word里面是什么

在Word里输入俄语字母,一打字字体就变成宋体了,俄语字母间间距...我不知道你这个俄语输入法补丁的字库用的是什么&#xff0c;如果是汉字库里好像就没办法调了&#xff0c;试一下把字体改成西文的Times New Roman、Arial等字体看有没有变化&#xff0c;如果没有&#xff0c;那就…

excel公式不自动计算_【纯干货】值得收藏的Excel日期计算公式!

点击上面“零壹快学”关注我们小伙伴们好&#xff0c;今天零壹学长给大家整理了一些常用的日期计算公式&#xff0c;赶紧往下看吧&#xff01;01根据身份证号计算出生年月--TEXT(MID(A2,7,8),"0-00-00")02根据身份证号提取性别IF(MOD(MID(A2,15,3),2),"男"…

项目开发流程_绿维文旅:旅游项目开发模式与流程

一、旅游项目开发模式旅游综合开发是立足旅游项目自有资源基础&#xff0c;以旅游产业为主导&#xff0c;以市场为导向&#xff0c;以资本为驱动&#xff0c;以资源整合为核心&#xff0c;通过集中土地、资本、技术、交通、劳动力等生产要素&#xff0c;推进土地开发、交通建设…

Java继承_java练习本(20190617)

公众号回复“1”&#xff0c;小刀拉你进学习交流群哟&#xff0c;妈妈再也不担心我学习没人陪伴啦~昨日翻译昨日翻译“The journey of a thousand miles begins with one step.”——Lao Tzu“千里之行始于足下。”——老子今日名言“Imagination was given to man to compensa…

爬虫 页面元素变化_爬虫 基本知识 萌新

爬虫定义网络爬虫&#xff08;又称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在FOAF社区中间&#xff0c;更经常的称为网页追逐者&#xff09;&#xff0c;是一种按照一定的规则&#xff0c;自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引…

gateway sentinel 熔断 不起作用_Sentinel 1.8.0 年度版本发布,熔断降级重构升级

简介&#xff1a;在经过数月的打磨后&#xff0c;Sentinel 1.8.0 版本正式发布&#xff01;该版本是本年度最重要的版本之一&#xff0c;包含大量特性改进与 bug 修复&#xff0c;尤其是针对熔断降级特性的完善升级&#xff08;支持任意统计时长、慢调用比例降级策略、熔断器事…

access设置0字段为null是因为类型转换失败_Apache Pulsar 2.6.1 版本正式发布:2.6.0 加强版,新增 OAuth2 支持

在 Apache Pulsar 2.6.0 版本发布后的 2 个月&#xff0c;2020 年 8 月 21 日&#xff0c;Apache Pulsar 2.6.1 版本正式发布&#xff01;Apache Pulsar 2.6.1 修复了 2.6.0 版本中的诸多问题&#xff0c;改进了一些功能&#xff0c;新增了对 OAuth2 的支持&#xff0c;覆盖 Br…

英特尔显卡linux管理_英特尔 11 代酷睿大揭秘:这次全是大招

英特尔在今年九月份正式推出了第 11 代酷睿移动处理器&#xff0c;这次英特尔将 10 纳米 SuperFin 工艺全面带到移动处理器上&#xff0c;同时还有全新的 Willow Cove 内核、Iris Xe 显卡、全新的酷睿及英特尔标志。这次面向消费级市场的英特尔第 11 代酷睿移动处理器又有哪些变…

lnmp php文件访问不了,记一次lnmp环境下无法执行php文件

lnmp环境搭建好后却无法正常执行php文件&#xff0c;坑爹啊&#xff01;~[错误状况]页面直接打印出php代码内容&#xff1b;php文件无法执行&#xff1f;&#xff1b;查看nginx配置文件&#xff1a;server { listen80;server_name xxxxx.com;access_log/var/log/nginx/xxxxx.ac…

file 选择的图片作为背景图片_酷炫!用Python把桌面变成实时更新的地球图片

如何拥有够酷炫逼格够高的桌面&#xff1f;本文教你轻松定制自己的桌面背景(建议带上耳机听一下地球的声音)最近疯狂迷恋地球卫星图和地球的卫星视频&#xff0c;看上面的视频简直极度舒适。不禁想把这种图片作为桌面背景图。这就产生抓取其背景图片作为桌面的想法。思路其实很…

摇杆怎么映射到键盘_[评测]YAMAHA PSRSX900:雅马哈升级幅度最大的高端编曲键盘键盘中国原创评测...

本文图片均由本人亲自拍摄&#xff0c;转载请注明出处。年前就收到这台国行PSR-SX900了。在这一个月特殊的日子里&#xff0c;不能出门&#xff0c;幸好有sx900的陪伴&#xff0c;让我可以天天弹琴、唱歌打发时间...现在很多地方开始逐渐复工了&#xff0c;我抽时间写下了这一个…

微软黑屏补丁_慎装微软最新Win7补丁 部分用户更新补丁后无法关机

清波科技2月9日报道 使用微软windows系统的用户&#xff0c;对于蓝屏肯定不陌生&#xff0c;不过现在还有比蓝屏更可怕的系统故障&#xff1a;无法关机和重启。近日&#xff0c;在微软更新了一个最新的Win7补丁后&#xff0c;有部分用户反馈&#xff1a;在试图从开始菜单关机或…