恭喜你获得治疗this“皮”的详细药方

栏目: JavaScript · 发布时间: 6年前

内容简介:观感度::star2::star2::star2::star2::star2:口味:清爽绿豆烹饪时间:15min

观感度::star2::star2::star2::star2::star2:

口味:清爽绿豆

烹饪时间:15min

你皮任你皮,我当你瓜皮。

恭喜你获得治疗this“皮”的详细药方

众所周知, this 在JavaScript中的指向一直很难让人理解,想要学好JavaScript, this 也是我们必须要搞清楚的。其实, this 并没有那么难,本文将力争带你治疗 this 的“皮”。

首先,来科普三个问题!

this是什么?

this 是声明函数时附加的参数 ,指向特定的对象,也就是隐藏参数。

比如LOL中各种隐藏的彩蛋,当水晶先锋斯卡纳在草丛里停留超过15秒不动,会模仿宠物小精灵。

“皮卡!皮卡!皮卡丘!”

“斯卡!斯卡!斯卡纳!”

恭喜你获得治疗this“皮”的详细药方

好,相信大家已经理解什么是 this 了,就是个隐藏参数,没有多么的神奇,其实 每个函数都可以访问 this

为什么要使用this?

this 提供了一种更加优雅的方式来隐式的传递对象引用。

通俗地说:就是说我们可以把API设计的更加简洁而且易于复用。

说人话:那就是** this 可以帮我们省略参数**。

this的指向

只需要理解并记住一句话,外加几种小情况,大家就可以完完全全的理解 this ,本文力争做到这一点。

好,注意听讲。

这句话就是 “ this 的指向在函数声明的时候是不会被确定的,只有函数执行的时候才被确定, this 最终指向的是调用它的对象 ”。

有人说这也太长了,记不住。

好,那缩短点。

一句话。

“this的指向决定于函数的调用方式”。

总结:

1. this 是声明函数时附加的参数,指向特定的对象,也就是隐藏参数。

2. this 可以帮我们省略参数。

3. this 的指向决定于函数的调用方式。

是不是很简单,搞清楚了这三点,我们下面将从八种情况来彻底理解 this 的指向问题。

直接上代码。

一、直到世界尽头

恭喜你获得治疗this“皮”的详细药方

(对,没错,有没有想起灌篮高手主题曲)

我们首先要了解一下世界观,分为三种情况。

1.在非严格模式下,浏览器中的尽头当然就是 window

2.在严格模式下也就是开启了 "use strict" 的情况下,尽头就是 undefined

3. node 的全局环境中尽头是 global

下文中情况主要从第一种非严格模式下来对 this 的指向进行解释和说明。

// 我们来看下面的两个:chestnut:。

function demo(){
  var user = “笛巴哥”;
  console.log(this.user);   // undefined
  console.log(this);       // window
}

demo();

// 这里的函数demo实际上是被window对象使用点语法所点出来的,如下:

function demo(){
    var user = “笛巴哥”;
    console.log(this.user);    // undefined
    console.log(this);        // window
}

window.demo();

// 可以发现和上面的代码结果一样

复制代码

二、画龙点睛

var obj = {
  user:”笛巴哥”,
  fn:function(){
     console.log(this.user);   // 笛巴哥
  }
}

obj.fn();

// 这里的this指向对象obj
// 注意看最后一行调用函数的代码
// obj.fn();

// 重要的事情说两遍!!
// this的指向在函数创建时是决定不了的
// 在调用的时候才可以决定,谁调用就指向谁

// this的指向在函数创建时是决定不了的
// 在调用的时候才可以决定,谁调用就指向谁

复制代码

三、点石成金

// 其实以上两点说的还不够准确,我们接着往下看

var obj = {
  user:”笛巴哥”,
  fn:function(){
     console.log(this.user); // 笛巴哥
  }
}
window.obj.fn(); 

// 这段代码跟上面的代码几乎是一样的
// 但是这里为什么没有指向window呢?
// 按你上面说的不是window调用的方法吗?
// 大家先停下来打个debugger思考一下为什么
// 想不明白没关系我们带着疑问来看下段代码

var obj = {
    a:1,
    b:{
        a:2,
        fn:function(){
            console.log(this.a); // 2
        }
    }
}

obj.b.fn();

// 这里执行的时候同样是对象obj通过点语法进行的执行
// 但是this同样没有指向window,这是为什么呢?

// 好,我们有几种情况需要记住:

// 1.如果一个函数中有this
// 但是它没有被上一级的对象所调用
// 那么this就会指向window(非严格模式下)

// 2.如果一个函数中有this
// 这个函数又被上一级的对象所调用
// 那么this就会指向上一级的对象

// 3.如果一个函数中有this
// 这个函数中包含多个对象
// 尽管这个函数是被最外层的对象所调用
// this却会指向它的上一级对象

var obj = {
  a:1;
  b:{
    // a:2,
    fn:function(){
       console.log(this.a);   // undefined
    }
  }
}
obj.b.fn();

// 我们可以看到,对象b中没有属性a,这个this指向
// 的也是对象b,因为this只会指向它的上一级对象
// 不管这个对象中有没有this要的东西

// 我们再来看一种情况

var obj = {
    a:1,
    b:{
        a:2,
        fn:function(){
            console.log(this.a);  // undefined
            console.log(this);   // window
        }
    }
}
var demo = o.b.fn;
demo();

// 在上面的代码中,this指向的是window
// 你们可能会觉得很奇怪
// 其实是这样的,有一句话很关键,再次敲黑板

// this永远指向的都是最后调用它的对象
// 也就是看它执行的时候是谁调用的

// 上面的例子中虽然函数fn是被对象b所引用了
// 但是在将fn赋值给变量demo的时候并没有执行
// 所以最终this指向的是window
复制代码

四、青梅竹马

function returnThis(){
  return this;
}
var user = {name:"笛巴哥"};

returnThis();            // window
returnThis.call(user);   // 笛巴哥
returnThis.apply(user) ; // 笛巴哥

// 这里就是Object.prototype.call
// 和Object.prototype.apply方法
// 他们可以通过参数来指定this

复制代码

五、矢志不渝

function returnThis(){
  return this;
}

var user1 = {name:"笛巴哥"};
var user1returnThis = return.bind(user1);
user1returnThis();             // 笛巴哥
var user2 = {name:"笛巴小哥"};
user1returnThis.call(user2);   // still 笛巴哥

// Object.prototype.bind通过一个新函数来提供了永久的绑定
// 而且会覆盖call和apply的指向

复制代码

六、乾坤大挪移

function Fn(){
  this.user = "笛巴哥";
}
var demo = new Fn();
console.log(demo.user);  // 笛巴哥

// 这里new关键字改变了this的指向
// new关键字创建了一个对象实例
// 所以可以通过对象demo点语法点出函数Fn里面的user
// 这个this指向对象demo

// 注意:这里new会覆盖bind的绑定
function demo(){
  console.log(this);
}

demo();             // window
new demo();         // demo
var user1 = {name:"笛巴哥"};
demo.call(user1);   // 笛巴哥

var user2 = demo.bind(user1);
user2();            // 笛巴哥
new user2();        // demo

复制代码

七、爱转角遇上return

// 当this遇上return时
function fn(){
  this.user = "笛巴哥";
  return{};
}
var a = new fn;
console.log(a.user);  // undefined

function fn(){
  this.user = "笛巴哥";
  return function(){};
}
var a = new fn;
console.log(a.user);  // undefined

function fn(){
  this.user = "笛巴哥";
  return 1;
}
var a = new fn;
console.log(a.user); // 笛巴哥

function fn(){
  this.user = "笛巴哥";
  return undefined;
}
var a = new fn;
console.log(a.user); // 笛巴哥

// 总结:如果返回值是一个对象
// 那么this指向就是返回的对象
// 如果返回值不是一个对象
// 那么this还是指向函数的实例

// null比较特殊,虽然它是对象
// 但是这里this还是指向那个函数的实例

function fn(){
  this.user = "笛巴哥";
  return null;
}
var a = new fn;
console.log(a.user); // 笛巴哥

复制代码

八、英雄登场

恭喜你获得治疗this“皮”的详细药方
// 最后我们介绍一种在ES6中的箭头函数
// 这个箭头函数中的this被加里奥的英雄登场锤的不行
// 皮不起来了
// 而且,在代码运行前就已经被确定了下来
// 谁也不能把它覆盖

// 这样是为了方便让回调函数中this使用当前的作用域
// 让this指针更加的清晰
// 所以对于箭头函数中的this指向
// 我们只要看它创建的位置即可

function callback(qdx){
  qdx();
}
callback(()=>{console.log(this)});        // window

var user = {
    name:"笛巴哥",
    callback:callback,
    callback1(){
      callback(()=>{console.log(this)});
    }
}
user.callback(()=>{console.log(this)});  // still window
user.callback1(()=>{console.log(this)}); // user
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

微创新

微创新

德鲁•博迪、雅各布•戈登堡 / 钟莉婷 / 中信出版社 / 2014-4-5 / 42.00

好产品不一定要颠覆,微小改进就能让用户尖叫! 引爆创新领域的全新方法论 互联网时代行之有效的5大创新策略 创业者、产品经理必读的创新行动指南 《怪诞行为学》作者 丹•艾瑞里 《影响力》作者 罗伯特•西奥迪尼 全球50位最具影响力的商业思想家之一丹尼尔•平克 周鸿祎、黎万强、罗振宇、牛文文、张鹏 联袂重磅推荐 为什么iPod可以在众多mp3产品中......一起来看看 《微创新》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具