箭头函数的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"…

matlab1 3倍频程,瞬时声压时域数据怎么用matlab进行1/3倍频程声压级分析

%A计权声压级频谱分析clc;clear;close all;%时域分析ywavread(abc.wav);%频域分析fs51200;%采样频率p02e-5;%参考声压f[1.00 1.25 1.600 2.00 2.50 3.15 4.00 5.00 6.30 8.0]; %基准中心频率f1[20.00 25.0 31.5 40.0 50.0 63.0 80];fc[f1,100*f,1000*f,10000*f]; %%%%%%%%%中心…

python paramiko长连接_【Python】 SSH连接的paramiko

paramiko*paramiko需要PyCrypto模块的支持paramiko支持通过SSH协议进行一些操作&#xff0c;比如远程执行命令&#xff0c;上下传文件等等用法&#xff1a;①  远程命令ssh paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())#指定当对方主机没…

php 共享内存列队,php中对共享内存,消息队列的操作

消息队列中的数据同样受到大小的约束&#xff0c;具体约束范围可通过msg_stat_queue的msg_qbytes看到。这段代码唯一有点小改动的地方就在接受消息时&#xff0c;指定了MSG_IPC_NOWAIT&#xff0c;不然如果目标队列没有数据&#xff0c;默认会一直等待。 一般会用到共享内存或消…

python文件路径拼接多出斜杠_浅谈python中拼接路径os.path.join斜杠的问题

浅谈python中拼接路径os.path.join斜杠的问题调试程序的过程中&#xff0c;发现通过os.path.join拼接的路径出现了反斜杠directory1/opt/apps/upgradePackagedirectory2icp_v1.8.0directory3os.path.join(directory1,directory2)print(directory3 : %s %directory3)执行结果dir…

matlab约当消去法,Gauss消去法解线性方程组(Matlab)

clear;clc;% Gauss消去法解线性方程组A[3 -5 6 4 -2 -3 8;1 1 -9 15 1 -9 2;2 -1 7 5 -1 6 11;-1 1 3 2 7 -1 -2;4 3 1 -7 2 1 1;2 9 -8 11 -1 -4 -1;7 2 -1 2 7 -1 9];%系数矩阵b[11 2 29 9 5 8 25];%n维向量yinv(A)*b %matlab的计算结果nlength(b);%方程个数nxzeros(n,1);%…

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

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

MATLAB仿真TSC在哪里找,-bash:tsc:找不到命令

我正在使用MAC并尝试安装TypeScript . 我使用安装打字稿sudo npm install -g typescript以下是结果Password:/Users//node/bin/tsc -> /Users//node/lib/node_modules/typescript/bin/tsc/Users//node/bin/tsserver -> /Users//node/lib/node_modules/typescript/bin/tss…

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…

python数据分析的步骤排序_Python数据分析

一.数据分析步骤1.提出问题2.理解数据3.数据清洗4.构建模型5.数据可视化二.朝阳医院2018年销售数据数据导入在文件路径前加r(转义符)文件可能有多个sheet&#xff0c;所以用sheet_name重命名参数dtypestr同意先按照字符串读入&#xff0c;之后再转换salesDf.head()&#xff0c;…

archlinux php mysql,arch linux上安装 httpd+php+mysql+ openssl(转)

arch linux上安装 httpdphpmysql openssl(转)[more]在arch linux安装则是非常的容易&#xff0c;只要执行&#xff1a;# pacman -Sy apache php mysql openssl根据提示选择输入Y即可安装&#xff01;1.修改apache配置文件默认的情况&#xff0c;apache是不支持PHP的&#xff0c…

ai人工智能python开发_Python才是人工智能AI的首选编程语言,你值得拥有……

在所有编程语言里&#xff0c;Python并不算萌新&#xff0c;从1991年发布第一个版本&#xff0c;至今已经快30年了。最近几年&#xff0c;随着人工智能概念的火爆&#xff0c;Python迅速升温&#xff0c;成为众多AI从业者的首选语言。根据数据平台 Kaggle发布的2017年机器学习及…

php bind_param,php – 在mysqli bind_param中绑定动态变量

当我尝试下面的代码时,它会给我一个警告mysqli_stmt::bind_param(): Number of elements in type definition string doesnt match number of bind variables$stmt $mysqli->prepare(SELECT * FROM users WHERE lname ? AND fname ?);$type "ss";$param ar…

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

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

php属性未定义,PHP-警告-未定义的属性:stdClass-修复?

我在错误日志中收到此警告&#xff0c;并想知道如何在代码中更正此问题。警告&#xff1a;PHP注意&#xff1a;未定义属性&#xff1a;stdClass :: $ records在440行的script.php中一些代码&#xff1a;// Parse object to get account ids// The response doesnt have the rec…

python做数据和大数据区别_不懂Python,不懂大数据的人,和咸鱼有什么区别?

原标题&#xff1a;不懂Python&#xff0c;不懂大数据的人&#xff0c;和咸鱼有什么区别&#xff1f;在这个处处充斥着大数据影响的时代之下&#xff0c;不懂Python&#xff0c;不懂大数据&#xff0c;你就可能轻易地错过身边的黄金。我们生活在数据密布的环境中&#xff0c;就…

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

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

php登录信息首页显示,首页登录后怎么在首页显示用户名以及隐藏登录框?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼index.php&#xff1a;登录页面用户名&#xff1a;密码&#xff1a;没有账号&#xff1f;立即注册——————————————————————————doaction.php&#xff1a;header("Content-type:text/html;charsetutf…