网易试题——关于箭头函数与this和arguments的关系

昨天做试题的时候遇到了这个题目

        var a = 1;function fn1() {console.log(this.a)}const fn2 = () => {console.log(this.a)}const obj = {a: 10,fn1: fn1,fn2: fn2}fn1()fn2()obj.fn1()obj.fn2()

哦这该死的网易,怎么出这么简单的题目,答案是:1,1,10,10   对,应该是这样的,吧?

可是再仔细一想,不对啊,我记得箭头函数的this对象好像不是在运行时基于函数的执行环境绑定的,他是有点奇怪的,事后仔细查了资料才知道,原来正确答案应该是 :1,1,10,1

一言概之,是因为:箭头函数的this和arguments只会从它自己所在作用域链的上一层继承,不会创建自己的this和argumrnts!!!(只有函数才会有this和arguments属性)

 让我再举几个例子给泥们looklook:

//普通函数var obj = {bar: function () {console.log(this); // 被obj调用,this指向{bar: ƒ}bar: ƒ ()__proto__: Object             var x = function() {console.log(this)//Window对象};return x;//闭包,this通常(即不使用箭头函数的情况)默认为全局对象,若在严格模式则为undefined}};var fn = obj.bar();fn() ; //箭头函数
// 创建一个含有bar方法的obj对象,// bar返回一个函数,// 这个函数返回this,// 这个返回的函数是以箭头函数创建的,// 所以它的this被永久绑定到了它外层函数的this。// bar的值可以在调用中设置,这反过来又设置了返回函数的值。var obj = {bar: function () {console.log(this); // {bar: ƒ}bar: ƒ ()__proto__: Object             var x = (() => this);return x;}};// 作为obj对象的一个方法来调用bar,把它的this绑定到obj。// 将返回的函数的引用赋值给fn。var fn = obj.bar();//此时外层函数已经运行完毕,他的this已经绑定到{bar: ƒ}这个环境console.log(fn() === obj); // trueconsole.log(fn()); // {bar: ƒ}bar: ƒ ()__proto__: Object  // 直接调用fn而不设置this,// 通常(即不使用箭头函数的情况)默认为全局对象// 若在严格模式则为undefined// 但是注意,如果你只是引用obj的方法,// 而没有调用它,this没有及时绑定到{bar: ƒ}这个环境var fn2 = obj.bar;// 那么调用箭头函数后,this指向window,因为它从 bar 继承了this。console.log(fn2()() == window); // true/* 此时等于在全局环境中调用 function () {console.log(this); // {bar: ƒ}bar: ƒ ()__proto__: Object             var x = (() => this);return x;}*/

 再来一粒,这次带有arguments

  //普通函数var name = "The Window";var object = {name: "My Object",getNameFunc: function () {console.log(arguments[0],'aa')//4console.log(this.name)//"My Object"return function () {//闭包,this通常指向windowconsole.log(arguments[0],'a')//5return this.name;};}};console.log(object.getNameFunc('4')('5'));  // The Window//箭头函数var name = "The Window";var object = {name : "My Object",getNameFunc : function(a) {console.log(this.name)//"My Object"console.log(arguments[0],'aa')//4return (a) => {console.log(arguments[0],'a')//4,这里是继承了上一层的argumentsreturn this.name;    //虽然是闭包,但成功继承了上一层的this};}};console.log(object.getNameFunc('4')('5'));  //"The Object"//函数都是箭头函数var name = "The Window";var object = {name : "My Object",getNameFunc : (a) => {console.log(this.name)//"The Window"//console.log(arguments[0],'aa')//errorreturn (a) => {//console.log(arguments[0],'a')//errorreturn this.name;    };}};console.log(object.getNameFunc('4')('5'));  //"The Window"//此时虽然是object调用了getNameFunc函数,但是箭头函数的this是指向上一层环境,即全局环境,所以this指向Window对象,而Window对象没有arguments,所以会出错

箭头函数还有一个值得注意的特性—— 无法使用call或者apply绑定this值。

由于 箭头函数没有自己的this指针,通过 call() 或 apply() 方法调用一个函数时,只能传递参数(不能绑定this),他们的第一个参数会被忽略。(这种现象对于bind方法同样成立)

          var name = "The Window";var object = {name : "My Object",getNameFunc : function(a) {console.log(this.name)//"outer"console.log(arguments[0],'aa')//4return (a) => {console.log(arguments[0],'a')//4return this.name;    };}};console.log(object.getNameFunc.call({name:'outer'},'4').call({name:'inner'},'5'));  //"outer" 

再来一题,也是网易的

        function fun() {return () => {return () => {return () => {console.log(this.name)}}}}var f = fun.call({ name: 'foo' });
f.call({name:'1'})()()//foo
f().call({name:'2'})()//foo
f()().call({name:'3'})//foo 

 你做对了吗?

推荐阅读

this 指向详细解析(箭头函数)

箭头函数

this

JavaScript中的匿名函数及函数的闭包

彻底理解js中this的指向,不必硬背。

对匿名函数的深入理解(彻底版)

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

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

相关文章

《JavaScript 高级程序设计》笔记 第1~5章

第1章 js是专为网页交互而设计的脚本语言,由3部分组成: ECMAScript,提供核心语言功能DOM文档对象模型,提供访问和操作网页内容的方法和接口BOM浏览器对象模型,提供与浏览器交互的方法和接口 js是一种脚本语言、解释…

【笔记】跨域重定向中使用Ajax(XHR请求)导致跨域失败

背景: 1、前端Web中有两个域名,a.com和b.com,其中a.com是访问主站(页面),b.com是数据提交接口的服务器(XHR请求) 2、a.com中用XHR调用b.com/cerate【没有指定协议】,保存…

javascript --- js中prototype、__proto__、[[Propto]]、constructor的关系

首先看下面一行代码: function Person(name){this.name name; } var person1 new Person; console.log(person1.__proto__ Person.prototype); console.log(person1.constructor Person);控制台打印如下: 可以看见,当使用构造函数(Person)构造一个实例(person1)时, 在后…

前端知识点整理收集(不定时更新~)

知识点都是搜集各种大佬们的,如有冒犯,请告知! 目录 原型链 New关键字的执行过程 ES6——class constructor方法 类的实例对象 不存在变量提升 super 关键字 ES6——...(展开/收集)运算符 面向对象的理解 关…

数据库四大特性与隔离级别

数据库四大特性ACID Atomicity (原子性) :事务(transaction)是由指逻辑上对数据的的一组操作,这组操作要么一次全部成功,如果这组操作全部失败,是不可分割的一个工作单位。 Consistency(一致性) :在事务开始以前&#…

重学《JavaScript 高级程序设计》笔记 第6章对象

第6章 面向对象的程序设计 ECMAScript中没有类的概念; 1.创建对象-历史 1.1 创建实例,添加方法和属性 → 对象字面量 缺点: 使用同一接口创建很多对象,产生大量重复代码 var person new Object() person.name "Y" pe…

Java-reflect(反射)初步理解_1

27.01_反射(类的加载概述和加载时机) A:类的加载概述 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。加载 就是指将class文件读入内存,并为之创建一个…

javascrip --- 构造函数的继承

两点需要注意的. 第一是在构造函数声明时,会同时创建一个该构造函数的原型对象,而该原型对象是继承自Object的原型对象 // 声明一个构造函数Rectengle function Rectangle(length, width) {this.length length;this.width width; }// 即:看见function 后面函数名是大写,一般…

Ruby实例方法和类方法的简写

创建: 2017/12/12 类方法 Sample.func实例方法 Sample#func转载于:https://www.cnblogs.com/lancgg/p/8281677.html

《JavaScript 高级程序设计》笔记 第7章及以后

第7章 函数表达式 匿名函数的name属性是空字符串;闭包是函数:闭包是有权访问另一个函数作用域中变量的函数;(P181 副作用,解释了点击li弹出循环最后值的原因)当某个函数第一次被调用时,会创建一个执行环境及相应作用域链&#xf…

[树形dp] Jzoj P1046 寻宝之旅

Description 探险队长凯因意外的弄到了一份黑暗森林的藏宝图,于是,探险队一行人便踏上了寻宝之旅,去寻找传说中的宝藏。藏宝点分布在黑暗森林的各处,每个点有一个值,表示藏宝的价值。它们之间由一些小路相连&#xff0…

javascript --- 使用语法糖class定义函数

本文讨论的是通过class声明的函数,有什么特点,或者说是指向了哪里. class A() {} // A是一个类// 要看class声明的函数指向哪里,只需将其[[Prototype]]属性打印到控制台,下面看看A和它的原型对象的指向 // 注:[[Prototype]]属性通过__proto__访问 console.log(A.__proto__…

前端知识点整理收集(不定时更新~)二

目录 require() 加载文件机制 线程和进程 线程 单线程 Nodejs的线程与进程 网络模型 初识 TCP 协议 三次握手 I/O I/O 先修知识 阻塞与非阻塞 I/O 同步与异步 I/O Git 基础命令 分支操作 修改远程仓库地址 远程分支获取最新的版本到本地 拉取远程仓库指定分支…

SpringBoot零基础入门指南--搭建Springboot然后能够在浏览器返回数据

File->new Project 修改默认包名,根据自己的喜好修改 选择初始化需要导入的包,尽量不要一开始就导入很多,特别是数据库,不然启动可能会有问题,创建好的目录如下: 配置文件写在application.properties下&…

JavaScript算法相关

1. 排序 1.1.冒泡排序 每一轮比较&#xff0c;从左至右交换相邻&#xff0c;每轮结束&#xff0c;最后一个为最大下一轮&#xff0c;需要比较的个数 - 1 j < len - i (范围动态缩小)共 len - 1 轮比较 function bubbleSort(arr) {var len arr.length;for (var i 1; i &…

javascript --- 编程风格

字符串 const a foobar; const b foo${a}bar; // 此处是反引号(tab键上) const c foobar;解构赋值 const [first, second] arr;function getFullName({ firstName, lastName }) { }function processInput(input) {return { left, right, top, bottom }; } const { left…

$ - 字符串内插

$ 特殊字符将字符串文本标识为内插字符串。 内插字符串是可能包含内插表达式的字符串文本。 将内插字符串解析为结果字符串时&#xff0c;带有内插表达式的项会替换为表达式结果的字符串表示形式。 此功能在 C# 6 及该语言的更高版本中可用。 与使用字符串复合格式设置功能创建…

数据结构基础知识

排序 参考&#xff1a;https://www.bilibili.com/video/av38482633/?spm_id_fromtrigger_reload 目录 排序 插入排序 直接插入排序 折半排序 希尔排序 ​ 交换排序 冒泡排序 快速排序 选择排序 堆排序 流量单位计算 什么是计数排序 复杂度分析&#xff1a; 什…

linux中安装软件,查看、卸载已安装软件方法

各种主流Linux发行版都采用了某种形式的包管理系统&#xff08;PMS&#xff09;来控制软件和库的安装。 软件包存储在服务器上&#xff0c;可以利用本地Linux系统上的PMS工具通过互联网访问。这些服务器称为仓库。 由于Linux发行版众多,目前还没有统一的PMS标准工具。 这里分别…

html5 --- 使用javascript脚本控制媒体播放

H5中的标签(<audio…/> 和 <video…/>)对于JS中的HTMLAudioElement对象和HTMLVideoElement对象 对象有以下几个方法: play(): 播放 pause(): 暂停播放 load(): 重新装载音频、视频 canPlayType(type): 判断该元素可播放type类型的音频、视频 下面是一个简单的音乐…