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(); // 1 var obj1={x:11};
obj1.showX=obj.showX;
obj1.showX(); // 11 show=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(); //

作为构造函数调用

当一个函数作为构造器使用时(通过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中的this(一)

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

  2. JS中this关键字详解

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

  3. JS 中 this 关键字详解

    本文主要解释在JS里面this关键字的指向问题(在浏览器环境下). 首先,必须搞清楚在JS里面,函数的几种调用方式: 普通函数调用 作为方法来调用 作为构造函数来调用 使用apply/call方法来调 ...

  4. 深入理解js中的apply、call、bind

    概述 js中的apply,call都是为了改变某个函数运行时的上下文环境而存在的,即改变函数内部的this指向. apply() apply 方法传入两个参数:一个是作为函数上下文的对象,另外一个是作 ...

  5. 深入浅出js事件

    深入浅出js事件 一.事件流 事件冒泡和事件捕获分别由微软和网景公司提出,这两个概念是为了解决页面中事件流(事件发生顺序)的问题. <div id="outer"> & ...

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

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

  7. 5.0 JS中引用类型介绍

    其实,在前面的"js的六大数据类型"文章中稍微说了一下引用类型.前面我们说到js中有六大数据类型(五种基本数据类型 + 一种引用类型).下面的章节中,我们将详细讲解引用类型. 1. ...

  8. 【repost】JS中的异常处理方法分享

    我们在编写js过程中,难免会遇到一些代码错误问题,需要找出来,有些时候怕因为js问题导致用户体验差,这里给出一些解决方法 js容错语句,就是js出错也不提示错误(防止浏览器右下角有个黄色的三角符号,要 ...

  9. JS中给正则表达式加变量

    前不久同事询问我js里面怎么给正则中添加变量的问题,遂写篇博客记录下.   一.字面量 其实当我们定义一个字符串,一个数组,一个对象等等的时候,我们习惯用字面量来定义,例如: var s = &quo ...

随机推荐

  1. matlab用法总结

    1. Matlab怎么判断空矩阵http://www.ilovematlab.cn/thread-48915-1-1.html a=[ ] if isempty(a) 2.matlab寻找多个最大值位 ...

  2. (转)ParallaxOcclusionMapping( POM ) DX9(转)

    http://blog.csdn.net/xujiezhige/article/details/7326606

  3. java 解析json字符串

    如果转载我的这篇文章请注明出处,谢谢! 最近工作中,需要解析json格式的字符串,恰好有个例子,感觉不错,拿来分享. 运行这个类需要加载jar包:ezmorph-1.0.6.jar.json-lib- ...

  4. Java8新特性 -- 四大内置的核心函数式接口

    可以把这些函数式接口作为方法的参数. 1.0 核心内置函数式接口一: 消费型接口@FunctionalInterfacepublic interface Consumer<T> { voi ...

  5. isa class superclass metaclass

    http://www.cnblogs.com/feng9exe/p/7232915.html Note: 其实这里的难点就在于对 和 的区分. .class 当 target 是 Instance 则 ...

  6. windows同时安装python2和python3

    系统之前安装了python2.7,现在准备装个python3.6 1:首先下载一个python3.6适合windows32位的包python-3.6.5.exe 然后直接默认双击安装,安装的时候勾选a ...

  7. MapReduce经典入门小案例

    /** * 单词统计 * @author fengmingyue * */ public class WordCount { public static void main(String[] args ...

  8. VRRP虚IP漂移

    简介 VRRP 是 Virtual Router Redundancy Protocol 的简称,即 虚拟路由冗余协议 . 原文地址:https://linux-network-programming ...

  9. MySQL基础----py全栈

    目录 MySQL基础----py全栈 一.引言 1.什么是数据? 2.什么是数据库(DB)? 3.什么是数据库管理系统(DBMS)? 4.什么是数据库系统? 5.数据库管理系统由来 6.什么是数据模型 ...

  10. spark上的一些常用命令(一)

    1. 加速跑 spark-sql --name uername --num-executors --driver-memory 8G --executor-memory 8G 2. 上传数据 建表 ) ...