博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
怎样使用this
阅读量:5939 次
发布时间:2019-06-19

本文共 4151 字,大约阅读时间需要 13 分钟。

this的使用

关于js里面有哪些难点,艹,js里面全是难点。。。什么闭包,原型,函数,对象,类型检测,this。。。但是作为一名正统的前端爱好者而言---这点痛算什么。今天我们来解决this这个点。由于牵扯到this,则必定会牵扯到函数,因为没有函数就没有this的存在的意思。

话不多说,Cut~

this的用法通常可以分为:

1. 作为对象的方法调用2. 作为普通函数调用3. 构造器调用4. call,apply调用

作为对象方法调用

var obj = {    name :"jimmy",    getName(){        return this.name;    }}console.log(obj.getName());  // jimmy

这里的this指向的是该对象.由于函数里面this是在运行时指定的,所以有一个诀窍就是,函数里面的this,指的是使用"."调用函数的所有者。

document.querySelector("#jimmy").onclick = function(){    console.log(this.tagName);  }

上面的this指的就是document.querySelector("#jimmy")。还有一种情况,当你使用的时候前面什么都没加,则这是函数中的this是global对象---window. 那上面的法则不是不对吗? 其实,在window里面调用函数,可以这样写.

function getName(){    console.log("jimmy");}window.getName();  //jimmygetName();  //jimmy

上面两种写法是完全等价的,只是一般比较懒,直接写成下面那一种了。

作为普通函数调用

上面已经说了,普通函数的this的不指定性,即,在使用之前函数的this都是不定的,直到函数执行的时候。

在es5中规定,当你的函数在全局中执行,该this会指向window.如果在严格模式下,则this为undefined

function name(){    console.log(this);}console.log(name());  // undefined

通常,当你的函数作为普通函数被调用的时候,this指向的是window,这个已经说过了~

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

在事件执行的时候,this指向的是该元素的引用

123
//jsdocument.querySelector('.name').onclick = function(){ console.log(this);}//得到的结果是.[object HTMLDivElement]

同样,加深印象。

构造器的调用

这其实很简单,就是使用new + funciton 创建的是一个对象,而不是一个函数.

function GetName(){    this.name = "jimmy";}GetName.prototype.getName = function(){    return this.name;}var get = new GetName();get.name(); //jimmyget.getName(); //jimmy

这里的this指向的就是getName.prototype上的。

但需要注意在构造器内不能显示的返回一个对象,否则你的实例化就会被破坏。

function GetName(){    this.name = "jimmy";    return {};  //显示返回一个对象}GetName.prototype.getName = function(){    return this.name;}var name = new GetName();console.log(name);  //{}var name2 = GetName();console.log(name2); //{}//显示返回一个非对象function GetName(){    this.name = "jimmy";    return "sam";  //返回非对象}GetName.prototype.getName = function(){    return this.name;}var name = new GetName();console.log(name); //["Object Object"]var name2 = GetName();console.log(name2);  //sam

call,apply调用

call和apply的区别,一个是传入参数为枚举,一个为数组

实际上,他们的用处还有扩展了函数的作用域

function getName(){    console.log(this.name);}var obj = {    name : "jimmy"}getName.call(obj);  //jimmy//相当于obj.getName = getName;obj.getName();  //这一个执行过程

使用call || apply改变this的作用域是非常关键的.

this的丢失
所谓的this丢失一般指的就是函数中this的丢失. 因为函数中的this只有在执行的时候才会确定指向。

var getId = document.getElement;getId("#name");  //这里会报错

上面的错误主要是因为,使用document.getElement时,this是指向document,在getElement里面会需要使用this上面的一系列方法,而上面的方式则和普通调用函数的方式一样,这时this的指向是全局的global,所以会造成有些方法使用不到. 这里可以改进:

var getId = (function(fn){    return funciton(){  //返回函数        return fn.apply(document,arguments);    }})(document.getElement);  //保存引用console.log(getId("#name"));

但其实上面写法还不如直接return好使.这里只是方便讲解.

而es5里面的bind函数应该算是一个将call和apply用到了点子上的方法。

var getName = function(){  console.log(this.tagName);  //DIV  var sam = function(){    console.log(this.tagName);  //undefined  }  sam();}document.querySelector('.name').onclick = getName;

上面的问题其实已经说到过了,就是出在函数作为普通函数调用的时候,里面的this永远指向的是 被赋予的对象。比如sam。 上面getName函数在执行的时候this是指向document.querySelector('.name')的.所以不会有什么问题.

改进的办法就是将this保存作用域(闭包).

var getName = function(){  var _this = this;  var sam = function(){    console.log(_this.tagName);  //DIV  }  sam();}document.querySelector('.name').onclick = getName;

由于闭包的长相完全是芙蓉姐姐,所以在es6中为了避免闭包的露脸加上了 箭头函数的feature.

var getName = function(){  var sam =()=>{    console.log(this.tagName);  }  sam();}document.querySelector('.name').onclick = getName;  //DIV

完美输出. 虽然这样会显得你比较牛逼,但是如果你把这个投入生产,保证leader分分钟切si 你。 md这么长.

这时候apply就完美登场了。

var getName = function(){    console.log(this.tagName);}document.querySelector('.name').onclick = function(){  getName.apply(this);};

是不是感觉少了很多代码~ 其实还可以再次改进,使用bind.

document.querySelector('.name').onclick = getName.bind(document.querySelector('.name'));

但这样其实还不如使用apply. 还需要注意的是call和apply都会直接执行函数,而bind只是返回一个函数.

apply和call的用法还有一个,就是借用其他对象的方法.
比如Math.max();函数,本来他只能接受枚举的参数,但可以使用apply进行装换

var num = [1,2,3,4,3,22];console.log(Math.max.apply(null,num));  //22

上面基本说明了apply和call的用处,但事实上,只要你用得好,apply和call的价值应该灰常大的。比如你还可以使用[].slice.call(arguments),用来将arguments类数组对象转化为一个真正的数组。

Ending~

转载地址:http://onttx.baihongyu.com/

你可能感兴趣的文章