ES6 逐点突破系列 -- 函数的扩展

news2024/11/17 5:43:12

}

f() // 1

var x = 1;

function foo(x, y = function() { x = 2; }) {

var x = 3;

y();

console.log(x);

}

foo() // 3

x // 1

上面代码中,函数foo的参数形成一个单独作用域。这个作用域里面,首先声明了变量x,然后声明了变量y,y的默认值是一个匿名函数。这个匿名函数内部的变量x,指向同一个作用域的第一个参数x。函数foo内部又声明了一个内部变量x,该变量与第一个参数x由于不是同一个作用域,所以不是同一个变量,因此执行y后,内部变量x和外部全局变量x的值都没变。

如果将var x = 3的var去除,函数foo的内部变量x就指向第一个参数x,与匿名函数内部的x是一致的,所以最后输出的就是2,而外层的全局变量x依然不受影响。

var x = 1;

function foo(x, y = function() { x = 2; }) {

x = 3;

y();

console.log(x);

}

foo() // 2

x // 1

P.S. 下面代码中,参数x = x形成一个单独作用域。实际执行的是let x = x,由于暂时性死区的原因,这行代码会报错”x 未定义“。

var x = 1;

function foo(x = x) {

// …

}

foo() // ReferenceError: x is not defined

2. reset参数


arguments对象不是数组,而是一个类似数组的对象。所以为了使用数组的方法,必须使用Array.prototype.slice.call先将其转为数组。rest 参数就不存在这个问题,它就是一个真正的数组,数组特有的方法都可以使用。

函数的length属性,不包括 rest 参数。

(function(a) {}).length // 1

(function(…a) {}).length // 0

(function(a, …b) {}).length // 1

P.S. rest 参数之后不能再有其他参数(即只能是最后一个参数)

3. 严格模式


ES2016 做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式

4. name属性


函数的name属性,返回该函数的函数名。

需要注意的是,ES6 对这个属性的行为做出了一些修改。如果将一个匿名函数赋值给一个变量,ES5 的name属性,会返回空字符串,而 ES6 的name属性会返回实际的函数名。

var f = function () {};

// ES5

f.name // “”

// ES6

f.name // “f”

bind返回的函数,name属性值会加上bound前缀。

function foo() {};

foo.bind({}).name // “bound foo”

(function(){}).bind({}).name // "bound "

5. 箭头函数


注意点

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

function foo() {

return () => {

return () => {

return () => {

console.log(‘id:’, this.id);

};

};

};

}

var f = foo.call({id: 1});

var t1 = f.call({id: 2})()(); // id: 1

var t2 = f().call({id: 3})(); // id: 1

var t3 = f()().call({id: 4}); // id: 1

上面代码之中,只有一个this,就是函数foo的this,所以t1、t2、t3都输出同样的结果。因为所有的内层函数都是箭头函数,都没有自己的this,它们的this其实都是最外层foo函数的this。

除了this,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:arguments、super、new.target。

由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。

(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

6. 尾调用优化


尾调用(Tail Call)是函数式编程的一个重要概念,指某个函数的最后一步是调用另一个函数。

function f(x){

return g(x);

}

函数调用会在内存形成一个“调用记录”,又称“调用帧”(call frame),保存调用位置和内部变量等信息。如果在函数A的内部调用函数B,那么在A的调用帧上方,还会形成一个B的调用帧。等到B运行结束,将结果返回到A,B的调用帧才会消失。如果函数B内部还调用函数C,那就还有一个C的调用帧,以此类推。所有的调用帧,就形成一个“调用栈”(call stack)。

尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。

尾递归

function Fibonacci (n) {

if ( n <= 1 ) {return 1};

return Fibonacci(n - 1) + Fibonacci(n - 2);

}

Fibonacci(10) // 89

Fibonacci(100) // 超时

Fibonacci(500) // 超时

function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {

if( n <= 1 ) {return ac2};

return Fibonacci2 (n - 1, ac2, ac1 + ac2);

}

Fibonacci2(100) // 573147844013817200000

Fibonacci2(1000) // 7.0330367711422765e+208

Fibonacci2(10000) // Infinity

改写递归函数

两个方法可以解决这个问题。方法一是在尾递归函数之外,再提供一个正常形式的函数。

function tailFactorial(n, total) {

if (n === 1) return total;

return tailFactorial(n - 1, n * total);

}

function factorial(n) {

return tailFactorial(n, 1);

}

factorial(5) // 120

函数柯里化

function currying(fn, n) {

return function (m) {

return fn.call(this, m, n);

};

}

function tailFactorial(n, total) {

if (n === 1) return total;

return tailFactorial(n - 1, n * total);

}

const factorial = currying(tailFactorial, 1);

factorial(5) // 120

第二种方法就简单多了,就是采用 ES6 的函数默认值。

function factorial(n, total = 1) {

if (n === 1) return total;

return factorial(n - 1, n * total);

}

factorial(5) // 120

严格模式

ES6 的尾调用优化只在严格模式下开启,正常模式是无效的。

这是因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。

func.arguments:返回调用时函数的参数。

func.caller:返回调用当前函数的那个函数。

尾调用优化发生时,函数的调用栈会改写,因此上面两个变量就会失真。严格模式禁用这两个变量,所以尾调用模式仅在严格模式下生效。

function restricted() {

‘use strict’;

restricted.caller; // 报错

restricted.arguments; // 报错

}

restricted();

尾递归优化的实现

function tco(f) {

var value;

var active = false;

var accumulated = [];

return function accumulator() {

accumulated.push(arguments);

总结

阿里十分注重你对源码的理解,对你所学,所用东西的理解,对项目的理解。

最新阿里蚂蚁金服四面(已拿offer)Java技术面经总结

最新阿里蚂蚁金服四面(已拿offer)Java技术面经总结

最新阿里蚂蚁金服四面(已拿offer)Java技术面经总结

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

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

相关文章

Axios发送ajax请求

}, // 请求体参数 data: { username: ‘admin’, password: ‘admin’ } }).then(response>{ // 响应状态码 console.log(response.status); // 响应状态字符串 console.log(response.statusText); // 响应头信息 console.log(response.headers); // 响应体 c…

docker 部署的 wordpress 接入阿里云短信服务 详细实操介绍

一、阿里云短信服务配置&#xff1a; 1、登录 阿里云短信服务 完成指引短信相关配置 2、创建RAM用户 并完成授权 出于安全及规范考虑 需通过RAM 用户来完成OponApl 接口调用&#xff0c;创建成功需完成短信接口&#xff08;AliyunDysmsFullAccess、AliyunDysmsReadOnlyAccess…

量检具管理有一套

量检具是用于测量和检验产品尺寸、形状和质量的工具。有一位年轻的工程师小张&#xff0c;他负责管理工厂的量检具&#xff0c;确保它们能够准确地测量产品尺寸和质量。有一天&#xff0c;小张发现量检具出现了一些问题。他注意到一些量具的读数不准确&#xff0c;导致生产出来…

加载资源文件失败

背景 自己以前装了一个海康的深度学习算法平台&#xff0c;试用期是一个月&#xff0c;过了一个月之后&#xff0c;因为没有有效注册码或者加密狗的支持了导致无法使用&#xff0c;于是打算卸载掉&#xff0c;在卸载一个软件的时候&#xff0c;无论是使用控制面板还是软件自带的…

SpringIOC核心源码

一、Spring IOC容器源码解析 1、Spring IOC容器的核心类 &#xff08;1&#xff09;BeanFactory与ApplicationContext &#xff08;2&#xff09;默认容器DefaultListableBeanFactory a. DefaultListableBeanFactory实现的接口 b.DefaultListableBeanFactory继承的类&#…

TCP/IP 在 Linux 内核中的实现

之前出了一个python的socket编程的文章&#xff0c;里面讲的是怎么进行socket编程。最近想到TCP/IP协议的原理&#xff0c;然后查阅资料后说是在操作系统级别实现的&#xff0c;python的socket模块只是一个接口。 本文就来谈一下Linux源码里实现TCP/IP协议簇的源代码在哪里&am…

记一次服务器崩溃事件

今天在安装Jenkins的时候&#xff0c;进行到插件安装这一步&#xff0c;本来一切顺利&#xff0c;结果最后安装完成之后一直进不去网页&#xff0c;显示连接超时&#xff0c;网上搜索了一圈也没发现什么相似的情况&#xff0c;当我疑惑的时候回到Linux控制台&#xff0c;发现命…

三品PDM电子行业解决方案介绍 电子企业PDM应用效果

随着全球化和技术创新的不断推进&#xff0c;电子行业正经历着前所未有的发展机遇。然而&#xff0c;随之而来的挑战也日益凸显&#xff0c;尤其是在产品数据管理PDM方面。本文将探讨电子行业在PDM方面的需求&#xff0c;并提出相应的解决方案&#xff0c;以帮助企业提升效率和…

css布局中的BFC问题

什么是边距重叠&#xff1f; 什么情况下会发生边距重叠&#xff1f; 如何解决边距重叠&#xff1f; 边距重叠&#xff1a; 两个box如果都设置了边距&#xff0c;那么在垂直方向上&#xff0c;两个box的边距会发生重叠&#xff0c;以绝对值大的那个为最终结果显示在页面上。…

解锁数据潜力:数据提取技术的无限可能

在当今信息爆炸的时代&#xff0c;数据已经渗透到我们生活的方方面面&#xff0c;成为推动社会进步和经济发展的重要力量。然而&#xff0c;仅仅拥有数据并不足以带来实质性的改变&#xff0c;关键在于如何有效地提取、分析和利用这些数据&#xff0c;以解锁其深藏的潜力。数据…

计算机中丢失vcruntime140_1.dll如何修复?分享7种常用解决方法

vcruntime140_1.dll缺失原因分析 软件卸载或更新不当在软件卸载或更新过程中&#xff0c;如果未能正确处理依赖关系&#xff0c;可能会导致vcruntime140_1.dll文件被错误地删除或损坏。 据统计&#xff0c;约有30%的DLL文件丢失问题是由于不当的卸载或更新操作引起的。 用户…

气体分离膜种类逐渐增多 市场规模不断扩大

气体分离膜种类逐渐增多 市场规模不断扩大 气体分离膜是由高分子材料组成的一种选择性膜。气体分离膜对不同种类的气体分子具有不同的透过率的选择性&#xff0c;可从混合气体中选择性分离某种特殊气体&#xff0c;从而起到分离、提纯等作用。与传统气体分离方法相比&#xff0…

EfficientNet大解析:如何重新定义模型效能?

EfficientNet大解析&#xff1a;如何重新定义模型效能&#xff1f; 1、abstract2、Compound Model Scaling3、EfficientNet Architecture4、results5、conclusion 论文地址: EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks 1、abstract 提出了一…

常见加密方式:MD5、DES/AES、RSA、Base64

16/32位的数据&#xff0c;最有可能就是使用md5加密的 使用对称加密的时候&#xff0c;双方使用相同的私钥 私钥&#xff1a;单独请求/隐藏在前端的隐藏标签当中 二、RSA非对称密钥加密 公钥加密&#xff0c;私钥解密 私钥是通过公钥计算生成的 加密解密算法都在js源文件当…

数据库层持久化

数据持久化层 冷热分离 冷热分离&#xff1a;将常用的“热”数据和不常使用的“冷”数据分开存储 冷热分离就是在处理数据时将数据库分成冷库和热库&#xff0c;冷库存放那些走到终态、不常使用的数据&#xff0c;热库存放还需要修改、经常使用的数据 业务需求出现了以下情况…

计算机毕业设计Python+LSTM+Tensorflow股票分析预测 基金分析预测 股票爬虫 大数据毕业设计 深度学习 机器学习 数据可视化 人工智能

基于TensorFlow-LSTM的股票预测系统开题报告 一、研究背景与意义 随着信息技术的飞速发展&#xff0c;股票市场作为现代经济活动的重要组成部分&#xff0c;其价格波动受到广泛关注。投资者们迫切希望通过科学的方法预测股票价格&#xff0c;以优化投资决策&#xff0c;实现利…

华为数通——链路聚合

链路聚合&#xff1a;又称为端口汇聚&#xff0c;是指两台交换机之间在物理上将两个或多个端口连接起来&#xff0c;将多条链路聚合成一条逻辑链路&#xff0c;从而增大链路带宽&#xff0c;多条物理链路之间能够相互冗余。 作用&#xff1a;增加链路带宽&#xff0c;同时提供…

模型泛化性测试

文章目录 准备工作场景描述训练数据集获取与训练 测试结论测试方案外机进行平移外机进行旋转外机即平移又旋转该螺纹孔位置 准备工作 场景描述 场景搭建如下如所示&#xff1a; 在该场景中&#xff0c;将机器人安置在桌子左上角处&#xff08;以面对显示器的视野&#xff09…

【Windows】“ONLYOFFICE 桌面编辑器 8.1 新特性大揭秘:全新 PDF 编辑器、幻灯片版式和更多更新“

【Windows】“ONLYOFFICE 桌面编辑器 8.1 新特性大揭秘&#xff1a;全新 PDF 编辑器、幻灯片版式和更多更新” 大家好 我是寸铁&#x1f44a; 【Windows】“ONLYOFFICE 桌面编辑器 8.1 新特性大揭秘&#xff1a;全新 PDF 编辑器、幻灯片版式和更多更新”✨ 喜欢的小伙伴可以点点…

WordPress网创自动采集并发布插件

网创教程&#xff1a;WordPress插件网创自动采集并发布 阅读更新&#xff1a;随机添加文章的阅读数量&#xff0c;购买数量&#xff0c;喜欢数量。 使用插件注意事项 如果遇到404错误&#xff0c;请先检查并调整网站的伪静态设置&#xff0c;这是最常见的问题。需要定制化服…