深入浅出js中的this
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相关推荐
- 浅入浅出JS中的eval及json
声明: 首先声明一下,本人是JS新手,所以不敢说深入,只是把最近对eval的学习经验拿出来跟大家分享,如果您是高手可略去不看. 适合读者: 对JS中的eval一知半解,不知eval是如何把字符串转换为 ...
- 求职季之你必须要懂的原生JS(中)
点击上方"IT平头哥联盟",选择"置顶或者星标" 一起进步- 互联网寒冬之际,各大公司都缩减了HC,甚至是采取了"裁员"措施,在这样的大环境 ...
- 掌握JS中的“this” (一)
译者注: 一般来说,function 翻译为函数, method 翻译为方法. 我们一般说, 某某对象的方法, 而不说 "某某对象的函数".原因是在面向对象中, 一个对象就是一个具 ...
- JS中this关键字详解
本文主要解释在JS里面this关键字的指向问题(在浏览器环境下). 阅读此文章,还需要心平气和的阅读完,相信一定会有所收获,我也会不定期的发布,分享一些文章,共同学习 首先,必须搞清楚在JS里面,函数 ...
- js中的设计模式之组合模式
Js中的组合模式 定义 是一种将对象组合成树状结构的层次结构模式,用来表示 整体-部分 的关系,使用用户对单个对象和组合对象具有一致的访问性. 详细描述 组合模式是一个树形结构,里面的数据可以是单个对 ...
- 在js中使用HashMap数据结构,在js中使用K,V数据结构
首先是定义一个HashMap方法,做基类(复制在js中即可,然后引用) //简单的哈希表,begin function HashMap() {/** Map 大小 * */var size = 0;/ ...
- [JavaScript] 探索JS中的函数秘密
函数长啥样? 把一些要重复使用的内容封装到函数内. function foo(title) {console.log(title) } foo('title') foo('dust') foo('he ...
- 在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查
Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用JavaScript开发并且能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect),.它当前支持M ...
- 在JS中最常看到切最容易迷惑的语法(转)
发现一篇JS中比较容易迷惑的语法的解释,挺有用的,转载下,与大家分享: js中大括号有四种语义作用 语义1,组织复合语句,这是最常见的 Js代码 if( condition ) { //... }e ...
最新文章
- asp.net客户端脚本验证小技巧
- Java8中一个极其强悍的新特性,很多人没用过(非常实用)
- JavaScript常用基础算法
- 前端学习(1978)vue之电商管理系统电商系统之为每一行数据提供单独的value
- 贵广网络跨界转型 实现智慧城市的平台创新
- Java多线程之后台线程不执行finally
- 将Ajax请求返回的json数据,转换成json对象
- 爬虫之Xpath的使用
- Android基础 写给新手的Android环境配置
- javascrit 数组方法总结(数组对象、栈,队列、重排序、操作数组方法、位置方法、归并方法、迭代方法)
- 有点累了?不如看看兵法三十六计。
- 信息安全技术及应用 互联网安全协议
- VB.Net教程图书目录
- 微信小程序快手小店登录
- 简单操作stm32f10xIO端口配置
- 问题:The given artifact contains a string literal with a package reference 'andro
- B2 - H - Historic Exhibition(二分图匹配+优化建图)
- T-SQL之连接查询、子查询、联合查询和交叉表查询
- 【daisy-framework】SpringBoot+MyBatis+Druid 多数据源
- Gbase 8s 产品特性
热门文章
- excel能设置从属值集吗_Excel中的从属组合框
- mix3信号测试软件,小米MIX3三大绝招保证信号质量,实测下来还优于iPhone XS Ma
- HT32F5232学习之利用dealy延时函数实现呼吸灯效果
- 多门店药品进销存系统源码 大型连锁药店管理系统源码
- i5 1135g7和i7 1165g7区别 i51135g7和i71165g7对比差多少
- 锥台上收发振子天线的隔离度
- html onblur ios,移动web端键盘问题、IOS安卓机input/textarea兼容性
- Topic Model
- 拓嘉辰丰:拼多多网店产品定价时要注意的问题有哪些?
- golang中:=是什么意思?