JS面试题--this指向+面试题

news2025/1/20 22:43:02

this其他补充

内置函数的绑定思考

image-20230109175317947

01_一些函数的this分析

// 1.setTimeout原理
// function hySetTimeout(fn, duration) {
//   fn.call(window)
// }

// hySetTimeout(function() {
//   console.log(this) // window
// }, 3000)

// setTimeout(function() {
//   console.log(this) // window
// }, 2000)

// 2.监听点击
// 这个只能调用一次onclick,再次调用会被覆盖
const boxDiv = document.querySelector(".box");
boxDiv.onclick = function () {
  console.log(this);
};
// 这个只能调用多次onclick,用会存储到一个数组里面
boxDiv.addEventListener("click", function () {
  console.log(this);
});
boxDiv.addEventListener("click", function () {
  console.log(this);
});
boxDiv.addEventListener("click", function () {
  // 原理 :fn。call(boxDiv)
  console.log(this);
});

// 3.数组.forEach/map/filter/find
// forEach的第一个参数是函数,第二个参数是this的绑定
var names = ["abc", "cba", "nba"];
names.forEach(function (item) {
  console.log(item, this);
}, "abc");
// map的第一个参数是函数,第二个参数是this的绑定
names.map(function (item) {
  console.log(item, this);
}, "cba");

规则优先级

image-20230109180611410

02_优先级-显示高于隐式绑定

var obj = {
  name: "obj",
  foo: function () {
    console.log(this);
  },
};

obj.foo();

// 1.call/apply的显示绑定高于隐式绑定
// obj.foo.apply('abc')
// obj.foo.call('abc')

// 2.bind的优先级高于隐式绑定
// var bar = obj.foo.bind("cba")
// bar()

// 3.更明显的比较
function foo() {
  console.log(this);
}

var obj = {
  name: "obj",
  foo: foo.bind("aaa"),
};

obj.foo(); //绑定显示绑定 [String: 'aaa']

03_优先级-new高于隐式绑定

var obj = {
  name: "obj",
  foo: function () {
    console.log(this);
  },
};

// new的优先级高于隐式绑定
var f = new obj.foo();

04_优先级-new高于显示绑定

// 结论: new关键字不能和apply/call一起来使用

// new的优先级高于bind
function foo() {
  console.log(this);
}

var bar = 

bar(); //aaa

var obj = new bar();

// new绑定 > 显示绑定(apply/call/bind) > 隐式绑定(obj.foo()) > 默认绑定(独立函数调用)

this规则之外 – 忽略显示绑定

image-20230109184526971

05_特殊绑定-忽略显示绑定

function foo() {
  console.log(this);
}

foo.apply("abc");
foo.apply({});

// apply/call/bind: 当传入null/undefined时, 自动将this绑定成全局对象
// foo.apply(null);
// foo.apply(undefined);

var bar = foo.bind(null);
bar();

this规则之外 - 间接函数引用

image-20230109184604420

06_特殊绑定-间接函数引用

// 争论: 代码规范 ;

var obj1 = {
  name: "obj1",
  foo: function () {
    console.log(this);
  },
};

var obj2 = {
  name: "obj2",
};

// obj2.bar = obj1.foo
// obj2.bar() //obj2
//  分号也是很关键的 ,不加分号会报错  会当成一行代码执行
(obj2.bar = obj1.foo)(); // 浏览器中是window  node中是global

0.测试代码
// 你不知道的JavaScript
function foo(el) {
  console.log(el, this.id);
}

var obj = {
  id: "awesome",
}[
  //  分号也是很关键的 ,不加分号会报错 -和obj{ id:'awesome'}[1,2,3].forEach(foo,obj)一起执行报错
  (1, 2, 3)
].forEach(foo, obj);
var nums = [1, 2, 3];
nums.forEach(foo, obj);


箭头函数 arrow function

image-20230109190252950

箭头函数的编写优化

image-20230109190349215

07_箭头函数的使用解析

// 1.编写箭头函数
// 1> (): 参数
// 2> =>: 箭头
// 3> {}: 函数的执行体
var foo = (num1, num2, num3) => {
  console.log(num1, num2, num3);
  var result = num1 + num2 + num3;
  console.log(result);
};

function bar(num1, num2, num3) {}

// 高阶函数在使用时, 也可以传入箭头函数
var nums = [10, 20, 45, 78];
nums.forEach((item, index, arr) => {});

// 箭头函数有一些常见的简写:
// 简写一: 如果参数只有一个, ()可以省略
nums.forEach((item) => {
  console.log(item);
});

// 简写二: 如果函数执行体只有一行代码, 那么{}也可以省略
// 强调: 并且它会默认将这行代码的执行结果作为返回值
nums.forEach((item) => console.log(item));
var newNums = nums.filter((item) => item % 2 === 0);
console.log(newNums);

// filter/map/reduce
var result = nums
  .filter((item) => item % 2 === 0)
  .map((item) => item * 100)
  .reduce((preValue, item) => preValue + item);
console.log(result);

// 简写三: 如果一个箭头函数, 只有一行代码, 并且返回一个对象, 这个时候如何编写简写
// var bar = () => {
//   return { name: "why", age: 18 }
// }
// 对象形式的简写,是个整体,告诉浏览器不是逻辑代码块而是一个对象
var bar = () => ({ name: "why", age: 18 });

this规则之外 – ES6箭头函数

image-20230109192938327

image-20230109193002221

08_箭头函数的this获取

// 1.测试箭头函数中this指向
// var name = "why"

var foo = () => {
  console.log(this);
};
// 箭头函数没有this,唯一确定this的方式是从上级作用域中寻找
foo();
var obj = { foo: foo };
obj.foo();
foo.call("abc");

// 2.应用场景
var obj = {
  data: [],
  getData: function () {
    // 发送网络请求, 将结果放到上面data属性中
    // 在箭头函数之前的解决方案
    // var _this = this
    // setTimeout(function() {
    //   var result = ["abc", "cba", "nba"]
    //   _this.data = result
    // }, 2000);
    // 箭头函数之后 this的指向在上级作用域中寻找,这里面的this就是指向getDate函数,因为getDate函数是setTimeout的上级作用域
    // getData是普通函数 又因为obj.getData()通过隐式绑定 绑定到obj,所以这里面的this就变成了obj对象,就可以调用date了
    setTimeout(() => {
      var result = ["abc", "cba", "nba"];
      this.data = result;
      console.log(this);
    }, 2000);
  },
};

obj.getData();

3.如果getData也是一个箭头函数,那么setTimeout中的回调函数中的this指向window {}
// 1.测试箭头函数中this指向
// var name = "why"

var foo = () => {
  console.log(22, this);

  var boo = () => {
    console.log(11, this);
  };
  boo();
};
// 箭头函数没有this,唯一确定this的方式是从上级作用域中寻找
foo();

// 2.应用场景
var obj = {
  data: [],
  aaa: [],
  getData: () => {
    console.log(this);
    // 发送网络请求, 将结果放到上面data属性中
    // 在箭头函数之前的解决方案
    // var _this = this
    // setTimeout(function() {
    //   var result = ["abc", "cba", "nba"]
    //   _this.data = result
    // }, 2000);
    // 箭头函数之后 this的指向在上级作用域中寻找,这里面的this就是指向getDate函数,因为getDate函数是setTimeout的上级作用域
    // getData是箭头函数 obj.getData()通过隐式绑定 不起效果,所以这里面的this依然是window node中是{}
    setTimeout(() => {
      var result = ["abc", "cba", "nba"];
        //这里的this是最上层的作用域window node中是{}
      this.data = result;
      console.log(this);
    }, 2000);
  },
};

obj.getData();


面试题一:

image-20230109221055341

var name = "window";

var person = {
  name: "person",
  sayName: function () {
    console.log(this.name);
  },
};

function sayName() {
  var sss = person.sayName;
  sss(); // window: 独立函数调用
  person.sayName(); // person: 隐式调用
  person.sayName(); // person: 隐式调用  (person.sayName)()其实相当于就是person.sayName();
  (b = person.sayName)(); // window: 赋值表达式(独立函数调用)只要是赋值表达式--就是独立函数的调用---开发中不会写这种代码
}

sayName();

面试题二:

image-20230109221112349

var name = "window";

var person1 = {
  name: "person1",
  foo1: function () {
    console.log(this.name);
  },
  foo2: () => console.log(this.name),
  foo3: function () {
    return function () {
      console.log(this.name);
    };
  },
  foo4: function () {
    return () => {
      console.log(this.name);
    };
  },
};

var person2 = { name: "person2" };

// person1.foo1(); // person1(隐式绑定)
// person1.foo1.call(person2); // person2(显示绑定优先级大于隐式绑定)

// person1.foo2(); // window(箭头函数没有this,不绑定作用域,上层作用域是全局)  node中是undefined
// person1.foo2.call(person2); // window  node中是undefined

// person1.foo3()(); // window(独立函数调用)  person1.foo3()是个结果没有调用主体
// person1.foo3.call(person2)(); // window(独立函数调用)--重点是只看最终的this绑定是谁,这里是独立函数的调用
// person1.foo3().call(person2); // person2(最终调用返回函数式, 使用的是显示绑定)

// person1.foo4()(); // person1(箭头函数不绑定this, 上层作用域this是person1)
// person1.foo4.call(person2)(); // person2(上层作用域被显示的绑定了一个person2)
// person1.foo4().call(person2); // person1(上层找到person1)person1.foo4()使上层作用域变成person1,又因为箭头函数没有this,不绑定call,而是从上层作用域中找

面试题三:

image-20230109221125149

var name = "window";

function Person(name) {
  this.name = name;
  (this.foo1 = function () {
    console.log(this.name);
  }),
    (this.foo2 = () => console.log(this.name)),
    (this.foo3 = function () {
      return function () {
        console.log(this.name);
      };
    }),
    (this.foo4 = function () {
      return () => {
        console.log(this.name);
      };
    });
}
// 函数每次new的时候都会创建一个新对象 每次的传入的this也是根据自己传入的参数自定义的this
var person1 = new Person("person1");
var person2 = new Person("person2");

person1.foo1(); // person1
person1.foo1.call(person2); // person2(显示高于隐式绑定)

person1.foo2(); // person1 (上层作用域中的this是person1)
person1.foo2.call(person2); // person1 (上层作用域中的this是person1)

person1.foo3()(); // window(独立函数调用)
person1.foo3.call(person2)(); // window
person1.foo3().call(person2); // person2

person1.foo4()(); // person1
person1.foo4.call(person2)(); // person2
person1.foo4().call(person2); // person1

var obj = {
  name: "obj",
  foo: function () {},
};

面试题四:

image-20230109221137715

var name = "window";

function Person(name) {
  this.name = name;
  this.obj = {
    name: "obj",
    foo1: function () {
      return function () {
        console.log(this.name);
      };
    },
    foo2: function () {
      return () => {
        console.log(this.name);
      };
    },
  };
}

var person1 = new Person("person1");
var person2 = new Person("person2");

person1.obj.foo1()(); // window 独立函数的调用
person1.obj.foo1.call(person2)(); // window  person1.obj.foo1.call(person2)是改变foo1的this指向为person2 但是foo1返回值为一个独立函数 独立函数的调用为window
person1.obj.foo1().call(person2); // person2  隐式绑定person2

person1.obj.foo2()(); // obj 上层作用域   主要看的返回值这个函数的上层作用域foo2是被谁调取的  这里是obj 调取的
person1.obj.foo2.call(person2)(); // person2  上层作用域   主要看的返回值这个函数的上层作用域foo2通过call改变this成为person2 所以是person2
person1.obj.foo2().call(person2); // obj 上层作用域是foo2通过隐式绑定变成obj, 箭头函数没有this 看上层作用域的指向

//

// 上层作用域的理解
// var obj = {
//   name: "obj",
//   foo: function() {
//      上层作用域是全局
//   }
// }

// function Student() {
//   this.foo = function() {
// 上层作用域是function Student
//   }
// }

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

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

相关文章

EEG论文阅读和分析:《Differential entropy feature for EEG-based emotion classification》

论文阅读《Differential entropy feature for EEG-based emotion classification》 论文的核心是提出差分熵作为特征,并且对差分差分熵和比例差分熵等特征进行对比研究。 算法流程步骤: 采样过程: A.预处理 根据受试者的压力反应&#xf…

零基础转行软件测试可行吗?

如今,随着人们对软件质量的要求越来越高,软件测试已经成为最热门的IT行业之一。不少非科班出身的转业者也纷纷开始观望这个行业,因此不少人会问,零基础转行软件测试有前途吗?答案显而易见,如果你想成为最炙…

【C语言】数据类型(基本类型、构造类型、类型转换)

⏰打卡:DAY1 🏆今日学习目标:数据类型(基本类型、构造类型、类型转换) ✨个人主页:颜颜yan_的个人主页 🎉专栏系列:从0开始学C语言 文章目录前言基本类型整型浮点型字符型构造类型数…

Mybatis学习——增删改(mysql8.0)

目录 一、配置文件 (一)添加mybatis依赖: (二)resources资源目录的配置 1.database.properties文件的设置 2.mybatis-config.xml文件的设置 二、引入原始类 三、DogDao接口,定义增删改功能 (一)单条数据增删改 1.新增 2.删除 3.修改 (二)多条…

Makefile详细教程

Makefile详细教程 我编写本指南是因为我永远无法完全理解 Makefile。 他们似乎充斥着隐藏的规则和深奥的符号,提出简单的问题并没有得到简单的答案。 为了解决这个问题,我花了几个周末的时间坐下来阅读所有关于 Makefile 的内容。 我已将最关键的知识浓…

【链表】leetcode206.反转链表(C/C++/Java/Js)

leetcode206.反转链表1 题目2 思路2.1 双指针法(迭代)2.2 递归法2.2.1 递归--从前往后翻转指针指向2.2.2 递归--从后往前翻转指针指向3 代码3.1 C版本(迭代)3.2 C版本(迭代递归)3.3 Java版本(迭…

【OpenDDS开发指南V3.20】第十章:Java Bindings

介绍 OpenDDS提供JNI绑定。Java应用程序可以像C++应用程序一样使用完整的OpenDDS中间件。 有关入门的信息,包括先决条件和依赖项,请参阅$DDS_ROOT/java/INSTALL文件。 Java版本9和更高版本使用Java平台模块系统。要在这些Java版本中使用OpenDDS,请将MPC特性Java_pre_jpms…

QT Echarts 联动共享数据表图 使用详解

Echarts是百度的一款可视化界面开发的平台,里面的地图以及数据可视化内容十分丰富,适合用于一些大屏数据显示项目或者一些ui界面开发。每一个ECharts图表使用一个无边框的QWebView来展示,这样多个不同类型的ECharts图表就是多个封装不同类型E…

kettle 筛选数据 并根据关键字段去重 设计

文章目录前言kettle 筛选数据 并根据关键字段去重 设计实现:1、配置sqlite 数据库链接2、先从test表里抽取数据3、将表输入查询的数据插入到excel里4、将筛选出来的数据根据id去重5、插入本地excel6、ETL 整体效果:7、测试:前言 如果您觉得有用的话,记得给博主点个赞…

安全轻量化股票看盘盯盘软件需要实现的功能和基本要求是什么?

有很多投资者是上班族的,因此是不能无时无刻盯盘看盘的,那么为了解决这个问题就需要用上轻量化股票看盘盯盘软件,那么一个安全的轻量化股票看盘盯盘软件需要具备哪些功能和基本要求呢?接下来小编为大家分析分析! 1.一定…

小试跨平台局域网文件传输工具NitroShare,几点感想

随着电脑系统国产化的推进,单位用的OA系统已转移到国产电脑上了,但是国产电脑上的操作系统基于Linux,软件商店里可选的应用软件还不够多,功能也还有待提高。为了提高处理效率,经常需要把文件从国产电脑传到Windows平台…

信息收集过程WAF绕过详解

今天继续给大家介绍渗透测试相关知识,本文主要内容是信息收集过程WAF绕过详解。 免责声明: 本文所介绍的内容仅做学习交流使用,严禁利用文中技术进行非法行为,否则造成一切严重后果自负! 再次强调:严禁对未…

浅析数据中心机架配电母线的应用及监控

摘要:本文先分析配电母线槽创新点和优势,然后结合湛江数据中心302机房母线槽建设对配电母线槽和列头柜两种供电方式进行经济效益对比,最后总结推广应用建议,以期为相关工程技术人员提供参考。 关键词:机架配电母线&a…

【动态路由和导航守卫】一.动态路由;二.路由中的查询参数;三.命名路由;四.命名视图;五.声明式导航 编程式导航;六.导航守卫

目录 一.动态路由 1.什么是动态路由? 2.动态路由如何进行参数的传递: (1)如何设置URL地址中的参数:/url/:参数名 (2)在组件中接收参数:this.$route.params.参数名 3.$route和$r…

最新版android-studio无法安装Lombok插件?魔改后可任意安装版本教程(附已魔改下载地址)

🤵‍♂️ 个人主页: 奇怪的守护神 👨‍💻 作者简介:十年全栈开发经验,团队负责人。喜欢钻研技术,争取成为编程达人 🎖️! 🗺️学海无涯苦作舟,🛤️…

【自学Python】Python字符串(string)

Python字符串(string) Python字符串(string)教程 字符串是一个不可改变的字节序列。字符串可以包含任意的数据,但是通常是用来包含可读的文本。 Python字符串(string) Python 字符串定义有五种形式,使用单引号、双引号、三个单引号 、三个双引号以及…

胡凡 《算法笔记》 上机实战训练指南 chap3 入门模拟: 3.2 查找元素

胡凡 《算法笔记》 上机实战训练指南 chap3 入门模拟: 3.2 查找元素 文章目录胡凡 《算法笔记》 上机实战训练指南 chap3 入门模拟: 3.2 查找元素【PAT B1041】考试座位号【PAT B1004】成绩排名【PAT B1028】人口普查解决过程(cpp)AC代码python实现AC代码pycode1pycode2未AC代码…

代码随想录算法训练营第7天 383.赎金信、454. 四数相加II、15.三数之和、18.四数之和

代码随想录算法训练营第7天 383.赎金信、454. 四数相加II、15.三数之和、18.四数之和 赎金信 力扣题目链接(opens new window) 给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构…

ERP系统到底能做什么?

ERP是什么?ERP即企业资源计划,ERP系统主要是优化企业内部的业务流程,用信息化管控的方式进行采购管理、库存管理、销售管理和财务管理等板块。它可以看作是进销存系统的进阶版,主要针对供应链中下游。 一、ERP系统怎么产生的&…

SpringBoot(项目创建使用+配置文件+日志文件)

目录 1. Spring Boot 项目创建 2. 写一个 Hello World 并运行 3. 配置文件的作用及格式 4. properties 配置文件的基本语法 5. 读取配置文件 6. yml 配置文件说明 7. properties 和 yml 的区别 8. SpringBoot 日志文件 8.1 日志的作用 8.2 自定义日志打印 8.3 日志…