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. 基于QT的一个简易的安防

    工程描述 opencv2.4.8 QT5 背景建模后,当有异物入侵时,把入侵的帧写到视频文件 使用BackgroundSubtractorMOG2背景建模 程序基于QT对话框 .pro #------ ...

  2. 编译驱动时出现"Cannot open file trace.h"错误

    编译驱动时出现"Cannot open file trace.h"错误 如题,用VS2013编译驱动是出现上述错误,原来是开启了WPP追踪导致的: 解决方案: 右键项目名-属性-W ...

  3. HDU-4675 GCD of Sequence 数学

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4675 题意:给一个大小为N的数列a[i],然后一个数M以及一个数K,要你求得一个数列b[i],其中b[ ...

  4. 安装禅道项目管理软件ZenTaoPMS

    服务器Ubuntu 13.04 且安装了上一篇随笔中的 AMP本文略去安装AMP过程.版本号满足要求(php>5.2 and mysql.2) 1.官网http://www.zentao.net ...

  5. cache 的简单认识与思考

    之前对NOSQL的总结是:基本功能是key-value, 然后各自附加特殊功能. 现在简单的来认识一下cache. 背景 大家都知道NoSQL, 大多数都是 key-value 型的数据库.有些内存型 ...

  6. hdu 3617 Happy 2009

    Happy 2009 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. 简单dp-poj-2231-Moo Volume

    题目链接: http://poj.org/problem?id=2231 题目大意: 给n个位置,求所有位置到其他n-1个位置的距离总和. 解题思路: 简单dp. o(n^2)的时间复杂度会超.先对这 ...

  8. rank() | dense_rank() | row_number() over(PARTITION BY sex order by age desc ) 的区别

    1.row_num() over()函数:根据某个字段排序后编号1,2,3.. select *,ROW_NUMBER() over ( order by majorid) as numfrom St ...

  9. 【Stage3D学习笔记续】真正的3D世界(三):纹理效果

    混合模式: 代码 示例是<Stage3D指南>中的直接弄出来的,可以通过点击键盘上的Q.W.E这3个按键,更换混合模式.模型和纹理,可以直观的查看不同混合模式的效果,住:下方的地形使用&q ...

  10. plsql developer的一些使用

    .PL/SQL Developer记住登陆密码 在使用PL/SQL Developer时,为了工作方便希望PL/SQL Developer记住登录Oracle的用户名和密码: 设置方法:PL -> ...