如何理解js中的this和实际应用中需要避开哪些坑
this是什么
this就是函数内部的关键字
看下面例子理解js中的this
// 例子1
function fnOne () {
console.log(this)
}
'use strict'
function fnOne () {
console.log(this)
}
// 例子2
let a = {
txt: 'hello world',
fn: function() {
console.log(this.txt)
}
}
a.fn()
window.a.fn()
// 例子3
let b = {
txt: 'hello',
obj: {
txt: 'world',
fn: function(){
console.log(this.txt)
console.log(this)
}
}
}
let c = {
txt: 'hello',
obj: {
// txt: 'world',
fn: function(){
console.log(this.txt)
}
}
}
b.obj.fn()
c.obj.fn()
let d = b.obj.fn
d()
// 例子4
function Fn () {
this.txt = 'hello world'
}
let e = new Fn()
e.txt
// 例子5
function Fn () {
this.txt = 'hello world'
return {txt:'hello'}
}
function Fn () {
this.txt = 'hello world'
return [1]
}
function Fn () {
this.txt = 'hello world'
return 1
}
function Fn () {
this.txt = 'hello world'
return null
}
function Fn () {
this.txt = 'hello world'
return undefined
}
let e = new Fn()
e.txt
// 带有{}或者[]返回值的方法实例化时this指向被改变
// 例子6
// 箭头函数与包裹它的代码共享相同的this对象
// 如果箭头函数在其他函数的内部
// 它也将共享该函数的arguments变量
let bob = {
_name: "Bob",
_friends: [],
printFriends: () => {
console.log(this._name)
console.log(this)
}
}
let bob = {
_name: "Bob",
_friends: [],
printFriends() {
console.log(this._name)
console.log(this)
}
}
let bob = {
_name: "Bob",
_friends: [1],
printFriends() {
this._friends.forEach((item) => {
console.log(this._name)
})
}
}
// arguments 对象
function square() {
let example = () => {
let numbers = [];
for (let number of arguments) {
numbers.push(number * number);
}
return numbers;
};
return example();
}
square(2, 4, 7.5, 8, 11.5, 21); // returns: [4, 16, 56.25, 64, 132.25, 441]
this的指向
this永远指向的是最后调用它的对象(箭头函数除外)
this的应用
如何改变函数的this指向 apply call bind
三者的区别apply和call改变函数this而且是立即执行。bind(es5新加方法注意兼容性)是复制函数,不会立即执行。根据各自执行时机的不同来选择采用哪种方案。
function Product(name, price) {
this.name = name
this.price = price
}
function Food(name, price) {
Product.call(this, name, price)
// Product.apply(this, arguments)
this.category = 'food'
}
console.log(new Food('cheese', 5).name)
bind用法和可以解决的问题
// 解决,从对象中拿出方法定义给新变量,但是希望方法的this值保持不变这时可以用bind来绑定this
this.x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 返回 81
var retrieveX = module.getX;
retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域
// 创建一个新函数,将"this"绑定到module对象
// 新手可能会被全局的x变量和module里的属性x所迷惑
var boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81
// bind配合setTimeout()
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
}
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
}
var flower = new LateBloomer();
flower.bloom(); // 一秒钟后, 调用'declare'方法
箭头函数的this使用注意事项
1、函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
2、不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
3、不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
4、不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
5、不能使用apply/call/bind
// 箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。下面是另一个例子。
function Timer() {
this.s1 = 0;
this.s2 = 0;
// 箭头函数
setInterval(() => this.s1++, 1000);
// 普通函数
setInterval(function () {
this.s2++;
}, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0
// 箭头函数可以让this指向固定化,这种特性很有利于封装回调函数。下面是一个例子,DOM 事件的回调函数封装在一个对象里面。
var handler = {
id: '123456',
init: function() {
document.addEventListener('click',
event => this.doSomething(event.type), false);
},
doSomething: function(type) {
console.log('Handling ' + type + ' for ' + this.id);
}
};如何理解js中的this和实际应用中需要避开哪些坑的更多相关文章
- 怎么理解js中的事件委托
怎么理解js中的事件委托 时间 2015-01-15 00:59:59 SegmentFault 原文 http://segmentfault.com/blog/sunchengli/119000 ...
- 如何更好的理解js中的this,分享2段有意思的代码
关于js中this的浅析,大家可以点击[彻底理解js中this的指向,不必硬背]这篇博客了解. 今天遇到2段比较有意思的代码. ----------------第一段----------------- ...
- 【学习笔记】六:面向对象的程序设计——理解JS中的对象属性、创建对象、JS中的继承
ES中没有类的概念,这也使其对象和其他语言中的对象有所不同,ES中定义对象为:“无序属性的集合,其属性包含基本值.对象或者函数”.现在常用的创建单个对象的方法为对象字面量形式.在常见多个对象时,使用工 ...
- 图文结合深入理解JS中的this值
文章目录 Js 中奇妙的this值 1. 初探this 2. this指向总结 2.1 普通函数调用 2.2 对象的方法调用 2.3 构造函数调用 2.4 利用call,apply,bind方法调用函 ...
- 详细理解JS中的继承
正式说继承之前,有两个相关小点: JS只支持实现继承,即继承实际的方法,不支持接口继承(即继承方法的签名,但JS中函数没签名) 所有对象都继承了Object.prototype上的属性和方法. 说继承 ...
- 图文结合深入理解 JS 中的 this 值
图文结合深入理解 JS 中的 this 值 在 JS 中最常见的莫过于函数了,在函数(方法)中 this 的出现频率特别高,那么 this 到底是什么呢,今天就和大家一起学习总结一下 JS 中的 th ...
- 深度理解js中var let const 区别
首先要理解js中作用域的概念 作用域:指的是一个变量的作用范围 1.全局作用域 直接写在script中的js代码,在js中,万物皆对象,都在全局作用域,全局作用域在页面打开时创建,在全局作用域中有一个 ...
- 深入理解JS中的对象(二):new 的工作原理
目录 序言 不同返回值的构造函数 深入 new 调用函数原理 总结 参考 1.序言 在 深入理解JS中的对象(一):原型.原型链和构造函数 中,我们分析了JS中是否一切皆对象以及对象的原型.原型链和构 ...
- 深入理解JS中的对象(三):class 的工作原理
目录 序言 class 是一个特殊的函数 class 的工作原理 class 继承的原型链关系 参考 1.序言 ECMAScript 2015(ES6) 中引入的 JavaScript 类实质上是 J ...
随机推荐
- PAT甲级——1061 Dating
1061 Dating Sherlock Holmes received a note with some strange strings: Let's date! 3485djDkxh4hhGE 2 ...
- QQ消息群发助手(超级简单)
大家好!我开发的小工具,效果见动图: 下载地址 QQ群发助手.rar 代码: def Login(): global Flag try: bot.Login(['-q',v1.get()]) tkin ...
- hibernate的乐观锁和悲观锁+事务
hibernate实现数据库操作的乐观锁和悲观锁参看:https://blog.csdn.net/chang_ge/article/details/79695813https://www.cnblog ...
- Redis为什么这么快以及持久化机制
1.首先我们谈一下为什么Redis快: 一. Redis是纯内存数据库,一般都是简单的存取操作,线程占用的时间很多,时间的花费主要集中在IO上,所以读取速度快. 二. 再说一下IO,Redis使用的是 ...
- JS替换变量中的文字字母
var text='Hello world, Hello world'; var b= text.replace('world','zhengxiaoya'); // 找到字符串中的第一个'world ...
- confidence intervals and precision|The One-Mean z-Interval Procedure|When to Use the One-Mean z-Interval Procedure
Confidence Intervals for One Population Mean When σ Is Known Obtaining Confidence Intervals for a Po ...
- SQL提高性能
1.对外键建立索引,大数据量时性能提高明显(建索引可以直接[Merge Join],否则还须在查询时生成HASH表作[Hash Join]) 2.尽量少使用inner join,使用left join ...
- eclipse 大括号改为C语言一样的代码块
如图:找到Windows->Preferences->Java->Code Style->Formatter: 然后,点击右边的Edit按钮: 按如下图完成
- Java IO: 字节和字符数组
原文链接 作者: Jakob Jenkov 译者:homesick 内容列表 从InputStream或者Reader中读入数组 从OutputStream或者Writer中写数组 在java中 ...
- 吴裕雄--天生自然HTML学习笔记:HTML 链接
HTML 链接 HTML 使用超级链接与网络上的另一个文档相连.几乎可以在所有的网页中找到链接.点击链接可以从一张页面跳转到另一张页面. HTML 超链接(链接) HTML使用标签 <a> ...