惠州微信小程序开发_详解JS中的this、apply、call、bind(经典面试题)

  • 栏目:公司新闻 时间:2021-01-11 14:16 分享新闻到:
<返回列表

详解JS中的this、apply、call、bind(经典面试题)     投稿:mrr   JS中的this、apply、call、bind是一道经典面试题,最好还是了解一下 this 的指向和 call、apply、bind 三者的区别。下面就跟随凡科小编一起学习this、apply、call、bind的知识吧

这又是一个面试经典问题~/(ㄒoㄒ)/~~也是 ES5中众多坑中的一个,在 ES6 中可能会极大避免 this 产生的错误,但是为了一些老代码的维护,最好还是了解一下 this 的指向和 call、apply、bind 三者的区别。

this 的指向

在 ES5 中,其实 this 的指向,始终坚持一个原理:this 永远指向最后调用它的那个对象,来,跟着我朗读三遍:this 永远指向最后调用它的那个对象,this 永远指向最后调用它的那个对象,this 永远指向最后调用它的那个对象。记住这句话,this 你已经了解一半了。

下面我们来看一个最简单的例子:

例 1:

 var name = "windowsName";
 function a() {
 var name = "Cherry";
 console.log(this.name); // windowsName
 console.log("inner:" + this); // inner: Window
 a();
 console.log("outer:" + this) // outer: Window

这个相信大家都知道为什么 log 的是 windowsName,因为根据刚刚的那句话“this 永远指向最后调用它的那个对象”,我们看最后调用 a 的地方 a();,前面没有调用的对象那么就是全局对象 window,这就相当于是 window.a();注意,这里我们没有使用严格模式,如果使用严格模式的话,全局对象就是 undefined,那么就会报错 Uncaught TypeError: Cannot read property 'name' of undefined。

再看下这个例子:

例 2:

var name = "windowsName";
 var a = {
 name: "Cherry",
 fn : function () {
 console.log(this.name); // Cherry
 a.fn();

在这个例子中,函数 fn 是对象 a 调用的,所以打印的值就是 a 中的 name 的值。是不是有一点清晰了呢~

我们做一个小小的改动:

例 3:

var name = "windowsName";
 var a = {
 name: "Cherry",
 fn : function () {
 console.log(this.name); // Cherry
 window.a.fn();

这里打印 Cherry 的原因也是因为刚刚那句话“this 永远指向最后调用它的那个对象”,最后调用它的对象仍然是对象 a。

我们再来看一下这个例子:

例 4:

 var name = "windowsName";
 var a = {
 // name: "Cherry",
 fn : function () {
 console.log(this.name); // undefined
 window.a.fn();

这里为什么会打印 undefined 呢?这是因为正如刚刚所描述的那样,调用 fn 的是 a 对象,也就是说 fn 的内部的 this 是对象 a,而对象 a 中并没有对 name 进行定义,所以 log 的 this.name 的值是 undefined。

这个例子还是说明了:this 永远指向最后调用它的那个对象,因为最后调用 fn 的对象是 a,所以就算 a 中没有 name 这个属性,也不会继续向上一个对象寻找 this.name,而是直接输出 undefined。

再来看一个比较坑的例子:

例 5:

 var name = "windowsName";
 var a = {
 name : null,
 // name: "Cherry",
 fn : function () {
 console.log(this.name); // windowsName
 var f = a.fn;
 f();

这里你可能会有疑问,为什么不是 Cherry,这是因为虽然将 a 对象的 fn 方法赋值给变量 f 了,但是没有调用,再接着跟我念这一句话:“this 永远指向最后调用它的那个对象”,由于刚刚的 f 并没有调用,所以 fn() 最后仍然是被 window 调用的。所以 this 指向的也就是 window。

由以上五个例子我们可以看出,this 的指向并不是在创建的时候就可以确定的,在 es5 中,永远是this 永远指向最后调用它的那个对象。

再来看一个例子:

例 6:

 var name = "windowsName";
 function fn() {
 var name = 'Cherry';
 innerFunction();
 function innerFunction() {
 console.log(this.name); // windowsName
 fn()

读到现在了应该能够理解这是为什么了吧(o ▽ )o。

怎么改变 this 的指向

改变 this 的指向我总结有以下几种方法:

使用 ES6 的箭头函数

在函数内部使用 _this = this

使用 apply、call、bind

new 实例化一个对象

例 7:

var name = "windowsName";
 var a = {
 name : "Cherry",
 func1: function () {
 console.log(this.name) 
 func2: function () {
 setTimeout( function () {
 this.func1()
 },100);
 a.func2() // this.func1 is not a function

在不使用箭头函数的情况下,是会报错的,因为最后调用 setTimeout 的对象是 window,但是在 window 中并没有 func1 函数。

我们在改变 this 指向这一节将把这个例子作为 demo 进行改造。

箭头函数

众所周知,ES6 的箭头函数是可以避免 ES5 中使用 this 的坑的。箭头函数的 this 始终指向函数定义时的 this,而非执行时。,箭头函数需要记着这句话:“箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this 为 undefined”。

例 8 :

 var name = "windowsName";
 var a = {
 name : "Cherry",
 func1: function () {
 console.log(this.name) 
 func2: function () {
 setTimeout( () = {
 this.func1()
 },100);
 a.func2() // Cherry

在函数内部使用 _this = this

如果不使用 ES6,那么这种方式应该是最简单的不会出错的方式了,我们是先将调用这个函数的对象保存在变量 _this 中,然后在函数中都使用这个 _this,这样 _this 就不会改变了。

例 9:

 var name = "windowsName";
 var a = {
 name : "Cherry",
 func1: function () {
 console.log(this.name) 
 func2: function () {
 var _this = this;
 setTimeout( function() {
 _this.func1()
 },100);
 a.func2() // Cherry

这个例子中,在 func2 中,首先设置 var _this = this;,这里的 this 是调用 func2 的对象 a,为了防止在 func2 中的 setTimeout 被 window 调用而导致的在 setTimeout 中的 this 为 window。我们将 this(指向变量 a) 赋值给一个变量 _this,这样,在 func2 中我们使用 _this 就是指向对象 a 了。

使用 apply、call、bind

使用 apply、call、bind 函数也是可以改变 this 的指向的,原理稍后再讲,我们先来看一下是怎么实现的:

使用 apply

例 10:

 var a = {
 name : "Cherry",
 func1: function () {
 console.log(this.name)
 func2: function () {
 setTimeout( function () {
 this.func1()
 }.apply(a),100);
 a.func2() // Cherry

使用 call

例 11:

 var a = {
 name : "Cherry",
 func1: function () {
 console.log(this.name)
 func2: function () {
 setTimeout( function () {
 this.func1()
 }.call(a),100);
 a.func2() // Cherry

使用 bind

例 12:

var a = {
 name : "Cherry",
 func1: function () {
 console.log(this.name)
 func2: function () {
 setTimeout( function () {
 this.func1()
 }.bind(a)(),100);
 a.func2() // Cherry

apply、call、bind 区别

刚刚我们已经介绍了 apply、call、bind 都是可以改变 this 的指向的,但是这三个函数稍有不同。

在 MDN 中定义 apply 如下;

apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数

语法:

fun.apply(thisArg, [argsArray])

thisArg:在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。

argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性请参阅本文底部内容。

apply 和 call 的区别

其实 apply 和 call 基本类似,他们的区别只是传入的参数不同。

call 的语法为:

fun.call(thisArg[, arg1[, arg2[, ...]]])

所以 apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。

例 13:

var a ={
 name : "Cherry",
 fn : function (a,b) {
 console.log( a + b)
 var b = a.fn;
 b.apply(a,[1,2]) // 3

例 14:

var a ={
 name : "Cherry",
 fn : function (a,b) {
 console.log( a + b)
 var b = a.fn;
 b.call(a,1,2) // 3

bind 和 apply、call 区别

我们先来将刚刚的例子使用 bind 试一下

 var a ={
 name : "Cherry",
 fn : function (a,b) {
 console.log( a + b)
 var b = a.fn;
 b.bind(a,1,2)

我们会发现并没有输出,这是为什么呢,我们来看一下 MDN 上的文档说明:

bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。

所以我们可以看出,bind 是创建一个新的函数,我们必须要手动去调用:

var a ={
 name : "Cherry",
 fn : function (a,b) {
 console.log( a + b)
 var b = a.fn;
 b.bind(a,1,2)() // 3

总结

以上所述是小编给大家介绍的JS中的this、apply、call、bind,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对凡科网站的支持!


分享新闻到:

更多阅读

惠州微信小程序开发_详解JS中的this、ap

公司新闻 2021-01-11
详细说明JS中的this、apply、call、bind(經典招聘面试题) 文章投稿:mrr JS中的this、apply、ca...
查看全文

广州凡科互联网科技股份有限公司招聘客

公司新闻 2021-01-11
招聘人数:18职位信息岗位要求:1、日常通过微信群进行与客户沟通,了解客户情况;2、负责...
查看全文

昆明网站建设难-霸首营销东莞网络维护

公司新闻 2021-01-10
最少3元/天,招代理商要是一千元预存银行开户,快排代理商商1000零元可开OEM代理商服务平台...
查看全文
返回全部新闻


区域站点: 南丰县小程序前端设计   南宫市有赞小程序   囊谦县小程序下载安装   南和县小程序模板源码   南华县小程序前端设计   南江县有赞小程序   南京市小程序下载安装   南靖县小程序模板源码   南康市小程序前端设计   南乐县有赞小程序   南陵县小程序下载安装   南宁市小程序模板源码   南平市小程序前端设计   南皮县有赞小程序   南市区小程序下载安装   南通市小程序模板源码   南投县小程序前端设计   南雄市有赞小程序   南溪县小程序下载安装   南阳市小程序模板源码   南漳县小程序前端设计   南召县有赞小程序   南郑县小程序下载安装   那坡县小程序模板源码   那曲县小程序前端设计   纳雍县有赞小程序   讷河市小程序下载安装   内黄县小程序模板源码   内江市小程序前端设计   内丘县有赞小程序   内乡县小程序下载安装   嫩江市小程序模板源码   聂荣县小程序前端设计   尼玛县有赞小程序   尼木县小程序下载安装   宁安市小程序模板源码   宁波市小程序前端设计   宁城县有赞小程序   宁德市小程序下载安装   宁都县小程序模板源码   宁国市小程序前端设计   宁海县有赞小程序   宁化县小程序下载安装   宁晋县小程序模板源码   宁陵县小程序前端设计   宁明县有赞小程序   宁南县小程序下载安装   宁强县小程序模板源码   宁陕县小程序前端设计   宁武县有赞小程序   宁乡市小程序下载安装   宁阳县小程序模板源码   宁远县小程序前端设计   农安县有赞小程序   磐安县小程序下载安装   盘锦市小程序模板源码   盘山县小程序前端设计   磐石市有赞小程序   盘州市小程序下载安装   蓬安县小程序模板源码   澎湖县小程序前端设计   蓬莱市有赞小程序   彭山县小程序下载安装   蓬溪县小程序模板源码   彭阳县小程序前端设计   彭泽县有赞小程序   彭州市小程序下载安装   偏关县小程序模板源码   平安县小程序前端设计   平昌县有赞小程序   平定县小程序下载安装   屏东县小程序模板源码   平度市小程序前端设计   平果县有赞小程序   平和县小程序下载安装   平湖市小程序模板源码   平江县小程序前端设计   平乐县有赞小程序   平凉市小程序下载安装   平利县小程序模板源码   平罗县小程序前端设计   平陆县有赞小程序   屏南县小程序下载安装   平泉市小程序模板源码   屏山县小程序前端设计   平顺县有赞小程序   平塘县小程序下载安装   平潭县小程序模板源码   平武县小程序前端设计   萍乡市有赞小程序   平乡县小程序下载安装   平阳县小程序模板源码   平遥县小程序前端设计   平阴县有赞小程序   平邑县小程序下载安装   平远县小程序模板源码   平舆县小程序前端设计   皮山县有赞小程序   普安县小程序下载安装   浦北县小程序模板源码   浦城县小程序前端设计   普洱市有赞小程序   普格县小程序下载安装   浦江县小程序模板源码   普兰县小程序前端设计   普宁市有赞小程序   莆田市小程序下载安装   迁安市小程序模板源码   乾安县小程序前端设计   潜江市有赞小程序   潜山市小程序下载安装  

友情链接: 微信小程序开发框 凡科小程序 免费打卡小程序怎 微信小程序 游戏 手机版

Copyright © 2002-2020 小程序下载安装_小程序模板源码_小程序前端设计_有赞小程序_线上签到小程序 版权所有 (网站地图) 备案号:粤ICP备10235580号