js中的this

来源:互联网 发布:齐天大圣孙悟空知乎 编辑:程序博客网 时间:2024/05/21 22:17

声明,原文摘自野狗公众号,本文只是本人对这篇文章的学习笔记

/*** * js中的this,javascript中的this指向并不是在函数定义的候确定的,而是在用的候确定的话说,函数的用方式决定了this的指向。 * js中,普通函数的用有三种:直接用、方法用和new用。除此之外,有一些特殊的用方式,比如通bind()将函数定到象之后再用、通call()、apply()用等。而es6引入了箭函数之后,箭函数,其this指向又有所不同。 *///1直接用,就是通函数名(...)的方式用的,这时候,函数内部的this指向全局象在浏览器中全局象是window,在node中全局象是global    //eg.1.//简单兼容浏览器和nodejs的全局const _global = typeof window === "undefined" ? global :window;function test(){    console.log(this === _global);//true}test();//直接//eg.2.(function(_global){    //通IIFE限定作用域    function test(){        console.log(this === _global);//true    }    test();//非全局作用域下的直接})(typeof window === "undefined" ? global : window);/** * // bind()直接用的影响 * function.prototype.bind()的作用是将当前函数与指定的定,并返回一个新函数,个新函数无以什么的方式用,其this始指向定的 *///eg.1.const obj = {};function test(){    console.log(this === obj,this);}const testObj = test.bind(obj);test(); //false,windowtestObj(); //true/** * call和applythis的影响 * 使用apply和call的候仍然需要注意,如果目本身是一个定了this象的函数,那apply和call不会像期那样执 *///eg.1.const obj = {};function test(){    console.log(this === obj);}//定到一个新象,而不是objconst testObj = test.bind({});test.apply(obj);    //true//期望this是obj,即出true//但是因ietestObj定了不是obj的象,所以会出falsetestObj.apply(obj);    //false//由此可,bind函数的影响是深的,慎用!/*** * 2.方法 * 方法用是指通过对象来用其方法函数,它是象.方法函数(...)这样用形式。种情况下,函数中的this指向方法的象。但是,同需要注意bind()的影响。 */const obj = {    //第一种方式,定义象的候定义其方法    test(){        console.log(this === obj);    }};//第二种方式,象定义好之后其附加一个方法(函数表达式)obj.test2 = function(){    console.log(this === obj);}//第三种方式和第二种方式原理相同//是象定义好之后其附加一个方法(函数定义)function t(){    console.log(this === obj);}obj.test3 = t;//也是为对象附加一个方法函数//但是个函数定了一个不是obj的其他obj.test4 = (function(){    console.log(this === obj);}).bind({});obj.test();     //trueobj.test2();    //trueobj.test3();    //true//受bind()影响,test4中的this指向不是obj,定到了新的空象上,如果定到obj上,则为trueobj.test4();    //false//里需要注意的是,后三种方式都是定义函数,在将其附加obj象作其方法。再次强,函数内部的this指向与定义无,受用方式的影响。/** * 方法中this指向全局象的情况 * 注意的是方法中而不是方法用中。方法中的this指向全局象,如果不是因bind(),那就一定是因不是用的方法用方式 *///eg.1.const obj = {    test(){        console.log(this === obj,this);    }};const t = obj.test;t();    //false,window//t就是obj的test方法,但是t(),其中的this指向了全局.class Handlers{    //里 $button 假是一个指向某个按的jQuery    constructor(data,$button){        this.data = data;        $button.on("click",this.onButtonClick);    }    onButtonClick(e){        console.log(this.data);    }}const handlers = new Handlers("string data",$("#someButton"));//#someButton 行点操作之后//出undefined//但期是出string  data//很然this.onButtonClick作一个参数入on()之后,事件触发时,是对这个函数行的直接用,而不是方法用,所以其中的this会指向全局象。要解决问题有很多种方法//1.是在es5中的解决方法之一var _this = this;$button.on("click",function(){    _this.onButtonClick();});//也可以通bind()来解决$button.on("click",this.onButtonClick.bind(this));//es6中可以通函数来理,在jQuery中慎用$button.on("click",e => this.onButtonClick(e));//不过请注意,将箭函数用作jQuery的回调时造成要小心函数内this的使用。jQuery大多数回函数(非箭函数)中的this都表示用目,所以可以写$(this).text()这样句,但jQuery无法改函数的this指向,同义完全不同。/** * new *///在es6之前,每一个函数都可以当作构造函数,通new用来生新的象(函数内无特定返回的情况下)。而es6改种状然class定义的用typeof运算符得到的仍然是"function",但它不能像普通函数一直接用;同,calss中定义的方法函数,也不能当作构造函数用new来用。//而在es5中,用new用一个构造函数,会建一个新象,而其中的this就指向个新象。没有什么念,因new本身就是计来建新象的。//eg.1.var data = "Hi";    //全局function AClass(data){    this.data = data;}var a = new AClass("Hello World");console.log(a.data);    //Hello Worldconsole.log(data);  //Hivar b = new AClass("Hello World");  //new 建的新console.log(a === b);     //false/** * 4箭函数中的this *///先来看看MDN 上函数的//An arrow function expression has a shorter syntax than a function expression and dose not bind its own this,argumengs,super,or new.target,Arrow functions are always anonymous.These function expressions are best suited for non-method functions,and they cannot be used as constructors.//里已清楚的明了,箭函数没有自己的this定。箭函数中使用的this,其实时直接包含它的那个函数或函数表达式中的this。//eg.1.const obj = {    test(){        const arrow = () => {            //里的thistest()中的this,            //由test()的用方式决定            console.log(this === obj);        };        arrow();    },    getArrow(){     return ()=>{        //里的this是getArrow()中的this,        //由getArrow()的用方式决定        console.log(this === obj);    };    }};obj.test();     //trueconst arrow = obj.getArrow();arrow();    //true//示例中的两个this都是由箭函数的直接外函数(方法)决定的,而方法函数中的this是由其用方式决定的。上例的用方式都是方法用,所以this都指向方法用的象,即obj。//箭函数让大家在使用包的候不需要太纠结this,不需要通像_this这样的局部量来临时引用this给闭包函数使用。来看一段Babel函数的转译可能能加深理解://ES6const obj = {    getArrow(){  return() =>{        console.log(this === obj);    };    }}//ES5,由Babel转译var obj = {    getArrow:function getArrow(){        var _this = this;       return function(){            console.log(_this === obj);        };    }}//另外需要注意的是,箭函数不能用new用,不能bind()到某个象(然binc()方法用没问题,但是不会期效果)。不管在什么情况下使用箭函数,它本身是没有定this的,它用的是直接外函数(即包含它的最近的一函数或函数表达式)定的this。

1 0