Q:this是什么?

A:this是Javascript语言的一个关键字,它代表函数运行时,自动生成的一个内部对象,在每个 function 中自动根据作用域(scope) 确定, 指向的是此次调用者。

Q:this的使用场景?

A: 1.普通函数调用。

  2.作为对象的方法来调用。

  3.作为构造函数调用。

  4.函数被call,apply,bind调用的时候。

栗子:

普通函数调用

function test1(){console.log(this);
}
test1();   // window

在非严格模式下,由于this必须是一个对象,所以就默认为指向全局对象window。在严格模式下,上面的代码则会出现不同的结果,如下:

function test1(){"use strict";console.log(this);
}
test1(); // undefined

再看看下面这段代码:

function test2(){this.x=2;
}
test2();
console.log(window.x);   // 2

由于普通函数的调用,this的值指向window。所以执行this.x的时候相当于执行了window.x,故window.x的值为2。

作为对象的方法来调用

var message = {content: "I'm a message!",showContent: function() {console.log(this.content);}
};message.showContent();   // I'm a message!

上面栗子是将函数保存为对象的属性, 这样就转化为一个方法, 可以通过对象调用这个方法。而当函数被当成对象的方法来调用时, 里面的 this 值就被设置为调用方法的对象。其实,不管被调用函数在声明时是属于方法,还是函数,当最终作为对象的方法来调用时,this都是指向方法的调用者,即母体对象。看看下面的栗子你就明白了。

var obj = {x: 1,showX: function() {console.log(this.x)}
}
obj.showX();  // 1var obj1={x:11};
obj1.showX=obj.showX;
obj1.showX();  // 11show=function(){console.log('show'+this.x);
}obj1.showX=show;
obj1.showX();   // show11

上面栗子中,在obj对象中,匿名函数在声明时就作为obj对象的一个属性,this直接指向obj对象。函数show在声明时是一个全局函数,函数里面的this指向window,但当最后作为对象obj1的一个属性时,其this便指向了对象obj1。但是,请注意,并不是所有函数作为对象的方法来调用时,this都会指向调用者,如下:

var obj = {x : 100,y : function(){setTimeout(function(){ console.log(this.x); }    , 1000);}
};obj.y();  // undefined

上面栗子中的this指向的是window对象,并不是我们期待的obj,所以会弹出undefined。所以在书写这类代码时,尽量避免这种写法,当然,你也可以在调用的时候将当时的this所指向的对象存在一个变量里,等到定时器运行时再用所存的变量去调用x,如下:

var obj = {x : 100,y : function(){var that = this;setTimeout(function(){ console.log(that.x); }, 1000);}
};obj.y();   // 100

作为构造函数调用

当一个函数作为构造器使用时(通过new关键字),它的this值绑定到新创建的那个对象。

function Message(content){this.content = content;this.showContent = function(){console.log(this.content);};
}var message = new Message("I'm a message!");
message.showContent();   // I'm a message!

再看看下面这个栗子。

function obj(){this.a=666;return 'abc';
}var obj=new obj();
console.log(obj);  // obj{a: 666} 

有木有看出什么?当一个带有return返回值的函数作为构造器去new一个新的对象时,return的值是被忽略的。是不是很神奇!

函数被call,apply,bind调用的时候

所有的函数都有apply()和call()这两个方法。我们可以通过这两个方法来改变函数的上下文, 在任何时候都有效, 用来显式地设置this的值。

apply()方法接收两个参数: 第一个是要设置为this的那个对象,第二个参数是可选的,如果要传入参数,则封装为数组作为apply()的第二个参数即可。

call()方法和apply()基本上是一样的,除了后面的参数不是数组,而是分散开一个一个地附加在后面。

function warrior(speed, strength){console.log("Warrior: " + this.kind +", weapon: " + this.weapon +", speed: " + speed +", strength: " + strength);
}var warrior1 = {kind: "ninja",weapon: "shuriken"
};var warrior2 = {kind: "samurai",weapon: "katana"
};warrior.call(warrior1, 9, 5);   // Warrior: ninja, weapon: shuriken, speed: 9, strength: 5
warrior.apply(warrior2, [6, 10]);   // Warrior: samurai, weapon: katana, speed: 6, strength: 10

在上面,我们通过对构造器warrior()传入不同的参数创建不同类型的对象, this将指向我们通过call() 和/或 apply()传入的对象。

在第一个函数调用中,我们使用call() 方法来将this设置为warrior1对象, 并传入需要的其他参数, 参数间用逗号分隔。在第二个函数调用中, 其实都差不多, 只是传入的是warrior2对象, 并将必要参数封装为一个数组。

除了call()和apply()以外,ECMAScript 5还增加了bind()方法,在调用一个函数或方法时也可以通过bind方法来绑定this对象。让我们看下面的栗子:

function warrior(kind){console.log("Warrior: " + kind +". Favorite weapon: " + this.weapon +". Main mission: " + this.mission);
}var attributes = {weapon: "shuriken",mission: "espionage"
};var ninja = warrior.bind(attributes, "ninja");ninja();   // Warrior: ninja. Favorite weapon: shuriken. Main mission: espionage

在这个栗子中, bind()方法的使用方式还是类似的, 但warrior.bind()创建了一个新的函数(方法体和作用域跟warrior()一样),并没有改动原来的warrior()函数。新函数的功能和老的一样, 只是绑定到了attributes对象。

注:bind方法和call,apply的区别在于,bind() 之后函数并没有执行,可以传给其他函数,在某个适当的时机再调用。

深入浅出js中的this相关推荐

  1. 浅入浅出JS中的eval及json

    声明: 首先声明一下,本人是JS新手,所以不敢说深入,只是把最近对eval的学习经验拿出来跟大家分享,如果您是高手可略去不看. 适合读者: 对JS中的eval一知半解,不知eval是如何把字符串转换为 ...

  2. 求职季之你必须要懂的原生JS(中)

    点击上方"IT平头哥联盟",选择"置顶或者星标" 一起进步- 互联网寒冬之际,各大公司都缩减了HC,甚至是采取了"裁员"措施,在这样的大环境 ...

  3. 掌握JS中的“this” (一)

    译者注: 一般来说,function 翻译为函数, method 翻译为方法. 我们一般说, 某某对象的方法, 而不说 "某某对象的函数".原因是在面向对象中, 一个对象就是一个具 ...

  4. JS中this关键字详解

    本文主要解释在JS里面this关键字的指向问题(在浏览器环境下). 阅读此文章,还需要心平气和的阅读完,相信一定会有所收获,我也会不定期的发布,分享一些文章,共同学习 首先,必须搞清楚在JS里面,函数 ...

  5. js中的设计模式之组合模式

    Js中的组合模式 定义 是一种将对象组合成树状结构的层次结构模式,用来表示 整体-部分 的关系,使用用户对单个对象和组合对象具有一致的访问性. 详细描述 组合模式是一个树形结构,里面的数据可以是单个对 ...

  6. 在js中使用HashMap数据结构,在js中使用K,V数据结构

    首先是定义一个HashMap方法,做基类(复制在js中即可,然后引用) //简单的哈希表,begin function HashMap() {/** Map 大小 * */var size = 0;/ ...

  7. [JavaScript] 探索JS中的函数秘密

    函数长啥样? 把一些要重复使用的内容封装到函数内. function foo(title) {console.log(title) } foo('title') foo('dust') foo('he ...

  8. 在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查

    Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用JavaScript开发并且能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect),.它当前支持M ...

  9. 在JS中最常看到切最容易迷惑的语法(转)

    发现一篇JS中比较容易迷惑的语法的解释,挺有用的,转载下,与大家分享: js中大括号有四种语义作用 语义1,组织复合语句,这是最常见的 Js代码  if( condition ) { //... }e ...

最新文章

  1. asp.net客户端脚本验证小技巧
  2. Java8中一个极其强悍的新特性,很多人没用过(非常实用)
  3. JavaScript常用基础算法
  4. 前端学习(1978)vue之电商管理系统电商系统之为每一行数据提供单独的value
  5. 贵广网络跨界转型 实现智慧城市的平台创新
  6. Java多线程之后台线程不执行finally
  7. 将Ajax请求返回的json数据,转换成json对象
  8. 爬虫之Xpath的使用
  9. Android基础 写给新手的Android环境配置
  10. javascrit 数组方法总结(数组对象、栈,队列、重排序、操作数组方法、位置方法、归并方法、迭代方法)
  11. 有点累了?不如看看兵法三十六计。
  12. 信息安全技术及应用 互联网安全协议
  13. VB.Net教程图书目录
  14. 微信小程序快手小店登录
  15. 简单操作stm32f10xIO端口配置
  16. 问题:The given artifact contains a string literal with a package reference 'andro
  17. B2 - H - Historic Exhibition(二分图匹配+优化建图)
  18. T-SQL之连接查询、子查询、联合查询和交叉表查询
  19. 【daisy-framework】SpringBoot+MyBatis+Druid 多数据源
  20. Gbase 8s 产品特性

热门文章

  1. excel能设置从属值集吗_Excel中的从属组合框
  2. mix3信号测试软件,小米MIX3三大绝招保证信号质量,实测下来还优于iPhone XS Ma
  3. HT32F5232学习之利用dealy延时函数实现呼吸灯效果
  4. 多门店药品进销存系统源码 大型连锁药店管理系统源码
  5. i5 1135g7和i7 1165g7区别 i51135g7和i71165g7对比差多少
  6. 锥台上收发振子天线的隔离度
  7. html onblur ios,移动web端键盘问题、IOS安卓机input/textarea兼容性
  8. Topic Model
  9. 拓嘉辰丰:拼多多网店产品定价时要注意的问题有哪些?
  10. golang中:=是什么意思?