【原】理解javascript中的this
最近的文章基本都是总结javascript基础内容的,因为我觉得这些东西很重要。而且很多时候你觉得你理解了,其实并没有你自认为的那么理解。十月份没怎么写文章,因为国庆出去玩的比较久,心变野了,现在是时候重新回到学习的轨迹了,今天要总结的是javascript中的this.
介绍this之前,先来两句话,这两句话比较重要,可以说贯穿全文。
1、this的最终指向的是那个调用它的对象
2、如果一个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象
下面通过一些代码示例来讲解this
1、window中的this
demo1
function test1(){
this.x = 1;
console.log(this.x);
}
test1(); //
function test2(){
var y = 2;
console.log(this.y); //undefined
console.log(this); //Window
}
test2();
上面的两个例子中,都是属于属于全局性调用,因此this就代表全局对象。也就是为什么test2打印出来的this.y会是undefined,因为this指向了 window.
2、在对象中使用this
demo2
var x=0;
var obj={
x:1,
fn:function(){
console.log(this.x);
}
}
obj.fn(); //
这里的this指向对象obj,因为调用的fn是通过obj.fn()执行的。
不过这里有个注意点,就是this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,这个是比较重要的一点。为了验证这句话,稍微改造一下上面的demo2
demo3
var x=0;
var obj={
x:1,
fn:function(){
console.log(this.x);
}
}
obj.fn(); // 1 跟上面的代码一样 // 修改了这里
var obj2=obj.fn;
obj2(); //
demo3中和demo2的不同之处在于,没有直接调用obj里面的fn函数,而是将其赋值给obj2,最终通过obj2来调用fn函数。
而obj2属于全局变量,因为fn里面的this指向了 window。这个也验证了上面那句话: this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁
demo4
var obj = {
x:1,
y:{
fn:function(){
console.log(this.x); //undefined
}
}
}
obj.y.fn();
如果一个对象中又包含有其他对象,this仅仅会指向它的上一级对象。
就像demo4中,fn里面调用this.x,这个this只会指向fn的上一级对象y。y中没有x这个变量,所以返回的是undefined。
稍微改造一下demo4,再次来验证一下:this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁
demo5
var obj = {
x:1,
y:{
x:2,
fn:function(){
console.log(this.x); //undefined
}
}
}
var obj2=obj.y.fn;
obj2(); // 因为此时fn中的this指向了window
3、在构造函数中使用this
demo6
function Fn(){
this.x=1;
}
var myFn=new Fn();
console.log(myFn.x); //
如果函数倾向于和 new 关键词一块使用,则我们称这个函数是构造函数, 在函数内部,this 指向新创建的对象。也就是说,这个this不是指向函数Fn,而是指向它的实例 myFn。
4、call和apply,改变this指向(这里顺便把call和apply给介绍了)
在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,也就是说,是为了改变函数体内部 this 的指向。
call和apply的区别就在于传递方式的不同,call在接收指定参数的形式是 someMethod.call(obj, arg1, arg2);
而apply在接收指定参数时的形式是 someMethod.apply(obj, [arg1, arg2]).或者someMethod.apply(obj, arg1),但是这个arg1必须是一个类数组对象
demo7
var personA = {
name: 'kobe',
sayName: function (hobby){
console.log(this.name + ' likes ' + hobby);
}
};
personA.sayName('basketball'); // 'kobe likes basketball'
var personB = {
name: 'James'
}
personA.sayName.call(personB, 'basketball'); // 'James likes basketball'
personA.sayName.apply(personB, ['basketball']); // 'James likes basketball'
personA.sayName('basketball'); 这段代码中,调用sayName()这个方法的对象是personA,因此sayName()内部的this指向就是personA对象。
personA.sayName.call(personB, 'basketball'); 本来sayName方法的this指向是personA对象,但是调用call/apply后,this对象指向了personB对象。
也可以这么理解,personA.sayName.call(personB, 'basketball')其实就是 personB.sayName(‘basketball’);
demo8
function PersonA(name,hobby) {
this.name = name,
this.hobby = hobby,
this.say = function() {
console.log(name +" likes " + this.hobby + '.');
}
}
function PersonB(name,hobby) {
PersonA.call(this,name,hobby);
}
var Fn=new PersonB('James','basketball');
Fn.say(); // James likes basketball.
虽然我们没有在PersonB对象里添加任何属性和方法,但是我们使用call()继承了原本属于PersonA 的属性和方法。就可以做到 PersonA 函数所有能做到的事情。
这里额外再穿插一下appy的使用一些场景
apply应用场景1:数组合并
var list1 = [0,1,2];
var list2 = [3,4,5];
[].push.apply(list1,list2); //或者 Array.prototype.push.apply(list1, list2); console.log(list1);// [0,1,2,3,4,5]
apply应用场景2:获取数组中的最大值或者最小值
var arr = [0,1,2,15,6];
var getMax=Math.max.apply(this,arr);
console.log(getMax); //
5、使用this的注意点
这里主要介绍 setTimeout或者setInterval中使用this的注意点
demo9
var name='james';
var person={
name:'koBe',
sayName:function(){
setTimeout(function(){
console.log(this.name);
},0);
}
}
person.sayName(); // james
因为setTimeout()这个异步函数调用的时候,内部的回调函数this的指向是window.刚好window中有一个 name为 james的标量。所以输出james.
那如何将setTimeout中的this指向 person呢。两种方式:
方法一:将this保存在一个变量中
demo10
var name='james';
var person={
name:'koBe',
sayName:function(){
var that=this; //将this存储在that中。
setTimeout(function(){
console.log(that.name);
},0);
}
}
person.sayName(); // koBe
将this保存在that中,这样,setTimeout调用this.name就变成了that.name了。
方法二:使用bind
demo11
var name='james';
var person={
name:'koBe',
sayName:function(){
setTimeout(function(){
console.log(this.name);
}.bind(this),0);
}
}
person.sayName(); // koBe
bind方法,起的作用和call,apply一样,都是改变函数/方法执行时,this的指向,确保这个函数/方法运行时this指向保持一致。
demo11中,通过bind方法将this对象绑定为person。那么回调函数在执行的时候,this指向还是person。
有误之处,欢迎指出
【原】理解javascript中的this的更多相关文章
- 转载 深入理解JavaScript中的this关键字
转载原地址: http://www.cnblogs.com/rainman/archive/2009/05/03/1448392.html 深入理解JavaScript中的this关键字 1. 一 ...
- 理解JavaScript中的原型继承(2)
两年前在我学习JavaScript的时候我就写过两篇关于原型继承的博客: 理解JavaScript中原型继承 JavaScript中的原型继承 这两篇博客讲的都是原型的使用,其中一篇还有我学习时的错误 ...
- 深入理解JavaScript中创建对象模式的演变(原型)
深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...
- 深入理解JavaScript中的属性和特性
深入理解JavaScript中的属性和特性 JavaScript中属性和特性是完全不同的两个概念,这里我将根据自己所学,来深入理解JavaScript中的属性和特性. 主要内容如下: 理解JavaSc ...
- 深入理解javascript中执行环境(作用域)与作用域链
深入理解javascript中执行环境(作用域)与作用域链 相信很多初学者对与javascript中的执行环境与作用域链不能很好的理解,这里,我会按照自己的理解同大家一起分享. 一般情况下,我们把执行 ...
- 【干货理解】理解javascript中实现MVC的原理
理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...
- 理解javascript中的策略模式
理解javascript中的策略模式 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 使用策略模式的优点如下: 优点:1. 策略模式利用组合,委托等技术和思想,有效 ...
- 深入理解javascript中的立即执行函数(function(){…})()
投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...
- js架构设计模式——理解javascript中的MVVM开发模式
理解javascript中的MVVM开发模式 http://blog.csdn.net/slalx/article/details/7856769 MVVM的全称是Model View ViewMod ...
- 全面理解Javascript中Promise
全面理解Javascript中Promise 最近在学习Promise的时候,在网上收集了一些资料,发现很多的知识点不够系统,所以小编特意为大家整理了一些自认为 比较好的文章,供大家更好地学习js中非 ...
随机推荐
- ORACLE数据库的导入及导出
今天在客户这里导入oracle数据库,第一次导入oracle数据库,在这里记录一下,以后备用. 一.使用PLSQL导出导入ORACLE数据库: 1.打开plsql-->工具---->导出用 ...
- ARMGNU伪指令
符号定义伪指令 .global,.local,.set,.equ .global 使得符号对连接器可见,变为对整个工程可用的全局变量 .global symbol .local 表示符号对外部不可见, ...
- android 让一个Activity停留几秒后再跳转
有时候我们需要在某个 Activity 停留几秒种,然后再跳到下一个 Activity.那么这个怎么实现呢? 一个方法是可以使用 Thread 的 sleep 函数,这个我们在 用Handler实现线 ...
- mysql5.7.13-windows 免安装版配置简介
1.下载mysql5.7.13-windows版本 (1)mysql5.7.13-win64版本百度云下载链接分享地址:链接:http://pan.baidu.com/s/1slMl4Ah 密码:w6 ...
- 【原】移动web动画设计的一点心得——css3实现跑步
今年3月份,由于公司业务需要,我转岗到微信产品部,离开了TID团队,人都是有感情的动物,更何况在一个团队呆了快 3 年,心中十分舍不得,鬼哥说了“天下没有不散的宴席...”,在我的世界里又多了一次离别 ...
- c++中this指针的用法
1. this指针的用处: 一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果.this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将 ...
- UVA 10564 Paths through the Hourglass[DP 打印]
UVA - 10564 Paths through the Hourglass 题意: 要求从第一层走到最下面一层,只能往左下或右下走 问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径 ...
- DEDE整站动态化或整站静态化设置方法,织梦栏目批量静态/动态方法
跟版网建站接到一个朋友提问,100多各栏目全部要从动态变成静态,里面的文章也要静态化,如何更快捷的设置dede的静态化或者动态化呢? 直接用DEDE后台的SQL命令行工具, SQL语句: DEDE整站 ...
- Three.js的光源投影
Three.js的光源默认不会导致物体间的投影,打开投影需要执行以下几步: 打开渲染器的地图阴影: renderer.shadowMapEnabled = true; 启用光线的投影:light.ca ...
- bootstrap 组件
bootstrap 组件 1下拉菜单(dropdown) 下拉菜单切换(dropdown-toggle) 下拉菜单对齐(dropdown-menu-right-右对齐) 下拉菜单分割线(di ...