this指向 箭头函数中的this call、apply和bind方法的用法以及区别

news/2024/7/19 16:33:35 标签: js, javascript

this

  • this 指向
  • 看看箭头函数的案例
  • call、apply和bind方法的用法以及区别
  • 来几个面试题试试

this 指向

在这里插入图片描述

1.普通函数的this:指向它的调用者,如果没有调用者则默认指向window.
2.箭头函数的this: 指向箭头函数定义时所处的对象,而不是箭头函数使用时所在的对象,默认使用父级的this 箭头函数的父级还箭头还是 就从父级开始 向上查找 直到有(实际上箭头函数里并没有 this,如果你在箭头函数里看到 this,你直接把它当作箭头函数外面的 this 即可。外面的 this 是什么,箭头函数里面的 this 就还是什么,因为箭头函数本身不支持 this。就默认看成使用父级的this)
对象中的函数叫方法
this 是当前对象的引用
如果函数是对象属性 或者类方法 this 就是当前对象
全局下调用的的函数 就是全局的对象 就是window

javascript">let obj = {
    name :"ThinkerWing",
    show:function () {
        // console.log(this); // 返回当前对象obj
        // return this.name;
        function render() {
            console.log(this);//Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …} 返回全局的对象
        }
        render();
    }
}
    obj.show();
console.log(this===window); //true
console.log(this===obj)  //false

函数是不属于任何对象的,this是函数运行时再决定的

javascript">  function user(name) {     //找到当前的参数  不然name变成window
      this.name = name; //这是属性 下面那条也是 属性的函数为方法
      this.show = function () {
         function render() {
             console.log(this);//返回window
         }
         render()
          console.log(this); //返回user 对象
      }
  }
  let TK = new user("ThinkerWing");
  TK.show();

看看箭头函数的案例

javascript">let name = {
    lastname:"wing",
    firstname:["thinker","Thinker"],
    show:function () {
        console.log(this);
        const self = this;
        return this.firstname.map(function (value) {
            return `${self.firstname}-${value}`
            // 由上例子知普通函数就是全局的对象 window 所以这边用常量改变this指针
            //(index) 0 thinker,Thinker -thinker
            //(index) 1  thinker,Thinker -Thinker
        })
    }
};
console.table(name.show());

了解一下箭头函数的this 指向 然后利用箭头函数 重写上一个案例

javascript">
var str = 'window';
const obj = {
    str:'obj',
    fn: ()=>{
        console.log(this.str);
    },
    fn2: function(){
        console.log(this.str, '当前词法作用域中的this');
        return {
            str: '我是fn2中的Obj 碰不到我的 箭头函数的this是指向上一级的',
            fn: ()=>{
                console.log(this.str);
            }
        }
    }
};

obj.newFn = ()=>{
    console.log(this.str);
};
obj.fn2(); //打印  obj 当前词法作用域中的this
obj.fn();//打印window
obj.newFn(); // 指向上一级的str  打印 window
var newObj = obj.fn2();
newObj.fn();//指向fn2()属性的上一级 即对象obj 打印obj的str即打印obj

了解了箭头函数的指向是父级的作用域 此时就不用担心普通函数的this指向全局

javascript">let name = {
    lastname:"wing",
    firstname:["thinker","Thinker"],
    show:function () {
        console.log(this); // 打印name 对象
        return this.firstname.map( (v)=> {
           console.log(this); //  打印值与上方的一样 同为name对象
            //箭头函数指向父级作用域
          return `${this.firstname}-${v}`
          //(index) 0 thinker,Thinker -thinker
            //(index) 1  thinker,Thinker -Thinker
        })
    }
};
console.table(name.show());

call、apply和bind方法的用法以及区别

先介绍一下apply是怎么传数组的 通过一个比大小的案例来解释

javascript">let arr = [0,1,2,3,4,5,6,7,8,9];
    console.log(Math.max.apply(Math,arr)); //打印9

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

javascript">   let TK = {
        name:"ThinkerWing"
    };
    function user(age,sex) {
        console.log(age+"岁的"+sex+":"+this.name);
    }
    user.call(TK,20,"男生"); //打印 20岁的男生:ThinkerWing
    user.apply(TK,[20,"男生"])  //打印 20岁的男生:ThinkerWing

来一个证明他们基本类似

javascript">function show() {
    alert(this.innerHTML)
}
let btn = document.querySelectorAll("button");
for (let i = 0 ; i<btn.length;i++){
    btn[i].addEventListener("click",event=>{
      show.apply(event.target) //此处call与apply是一样的
        // console.log(this) // 打印 window 因为这里箭头函数的父级就是window
    })
}

重新回顾一下this的指向 为什么Age能打印20而fun 同样也是this.age却不行呢?
因为Age指向了全局 而fun中的指向了obj对象,对象中无age定义。

javascript">    var name = "ThinkerWing", age = 20;
    var obj = {
        name : 'TK',
        Age: console.log(this.age), //打印20
        fun:function () {
            console.log(this.name+"年龄"+this.age);
        }
    };
    obj.fun() //打印 TK年龄undefined
javascript">var name = "ThinkerWing", age = 20;
    var obj = {
        name : 'TK',
        Age: console.log(this.age), //打印20
        fun:function (a,b,c) {
            console.log(this.name+"年龄"+this.age+a+b+c);
        }
    };
    var demo = {
        name:'baby',
        age:20
    };
    //缺少三个传参  因为这边只想调用年龄 姓名 证明三个实现是一样的
    obj.fun.call(demo);  //baby年龄20undefinedundefinedundefined
    obj.fun.apply(demo);  //baby年龄20undefinedundefinedundefined
    obj.fun.bind(demo)();  //baby年龄20undefinedundefinedundefined
    obj.fun.call(demo,"相遇","福州",2019); //baby年龄20相遇福州2019
    obj.fun.apply(demo,["相遇","福州",2019]);//baby年龄20相遇福州2019
    obj.fun.bind(demo,"相遇","福州",2019)();//baby年龄20相遇福州2019
    obj.fun.bind(demo,["相遇","福州",2019])();//baby年龄20相遇,福州,2019undefinedundefined
    //以上出了 bind 方法后面多了个 () 外 ,结果返回都一致!
    // 由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行

All in all (总的来说综上所述):

call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:

call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面

apply 的所有参数都必须放在一个数组里面传进去

bind 除了返回是函数以外,它 的参数和 call 一样。

当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!

来几个面试题试试

javascript">    var obj = {
        foo: function(){
            console.log(this)
        }
    }

    var bar = obj.foo
    obj.foo() 
    bar() 

答案: obj.foo() // 打印出的 this 是 obj
bar() // 打印出的 this 是 window

因为this就是对当前对象的引用 所以obj.foo() 打印了对象
bar() 是定义对象中的函数 普通的函数就是全局对象

javascript">var x = 12;
function test() {
    console.log(this.x);
}

var obj = {
    x:45,
    ss:function () {
        console.log(this.x);
    }
};
var bar = obj.ss;
test(); 
obj.ss();
bar()

答案:
test(); //12
obj.ss(); //45
bar() //12
test 只是普通函数 this指向全局 全局变量 x =12;
这题同上题相似 只是换了数据

javascript">var name = "222";
    var a = {
        name :"111",
        say : function () {
            console.log(this.name);
        }
    };
    var fun = a.say;
    fun();   // 答案
    a.say(); //答案
    var b = {
        name : "333",
        say : function (fun) {
            fun()
        }
    };
    b.say(a.say); //答案
    b.say = a.say;
    b.say(); // 答案
	 fun();   //222
     a.say(); //111
     b.say(a.say); //222
     b.say(); // 333

第一问 fun =a.say , 只是一个普通函数 全局变量 222
第二问 a.say() 指向对象 a 的name 111
第三问 先看括号中的a.say 类似将fun=a.say 然后执行fun() fun()的归属是window 不是某个对象中的
第四问 b.say() 指向对象 b 的name 333


http://www.niftyadmin.cn/n/883353.html

相关文章

openBrowser

ssh地址 https://gitee.com/yaoxin001/openBrowser.git QT_openBrowser 介绍 基于QT 一个开源的文件浏览器 目前支持 .dcm .mha .mhd .stl .off .vtk .vtu .bmp .jpg .pbm .pgm .png .ppm .xbm .xpm 等文件的浏览和前处理 (off mha mhd vtk vtu格式文件目前需要自己更改下源…

期末不挂科:数据库零基础超详细之临时抱佛脚笔记

期末数据库复习ER图关系代数三级目录参考&#xff1a;ER图参考&#xff1a;关系代数ER图 百度百科&#xff1a; 在ER图中有如下四个成分&#xff1a; 矩形框&#xff1a;表示实体&#xff0c;在框中记入实体名。 菱形框&#xff1a;表示联系&#xff0c;在框中记入联系名。 椭…

原型与继承

这里写目录标题一级目录原型的初步认识没有原型的对象也是存在的原型方法与对象方法优先级函数拥有多个长辈js中的prototype和__proto__的区别&#xff1a;自定义对象的原型设置constructor引用hasOwnProperty 和 in 属性检测差异改变构造函数不是继承 继承是原型的继承多态原型…

Study-VTK:QVTKOpenGLWidget/QVTKOpenGLNativeWidget 显示全黑,未设置眼色缓冲

QVTKWidget有默认的RenderWindow&#xff0c;而QVTKOpenGLWidget是没有的&#xff08;是空指针&#xff09; 如果继承重写QVTKOpenGLWidget需要设置QSurfaceFormat&#xff08;QSurface的颜色缓冲&#xff09; vtkOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(8)…

Deepin 使用教程:前言

19-20年使用Deepin15.11一段时间&#xff0c;各方面体验感都很好。后来出了Deepin20我就迫不及待的尝试了&#xff0c;一天卡死两次就放弃了。等了一年后20.2.2同样一天卡死两次。还搞出了UOS&#xff0c;个人喜好&#xff0c;只看名字我觉得UOS没Deepin好听。 之前用Deepin的…

网易云项目 ----轮播图(BetterScroll 2.x 的使用)

这里写目录标题用BetterScroll 2.x 和网易云的api接口实现轮播图调用网易云api下载安装网易云音乐的api接口router.js 和 main.js 的配置组件banner.vueBetterScroll 2.x的使用$refswatchApp.vue用BetterScroll 2.x 和网易云的api接口实现轮播图 调用网易云api 下载安装网易云…

qt creator 打开qss文件 语法高亮

qt 默认只有css文件高亮&#xff0c;你可以把qss文件重命名为css&#xff0c;或者 再下边这里增加*.css;.CSSL;.qss Deepin 系列教程 Deepin 使用教程&#xff1a;前言

音乐播放器的设计与实现 功能要求:设计一款基于HTML5音频技术的音乐播放器,要求实现音乐的播放、暂停、音量大小调节、上一首和下一首切换,运行效果如图所示

本地资源在谷歌浏览器上是无法快进的。这个是重点!!!有很多解决方法&#xff0c;我直接用火狐就ok了 https://www.gaitubao.com/# 改图宝链接 用于修改歌曲头像 大小标准显示才正常 我用的大小为300&#xff0c;300 我用的图标全都来自iconfont Iconfont-阿里巴巴矢量图标库 贴…