ES5中的this
参考资料:>>>
this的指向
在 ES5 中,其实 this 的指向,始终坚持一个原理:
this 永远指向最后调用它的那个对象
下面我们来看一个最简单的例子:(例子均来自参考资料中的经典例子)
例 1:
var name = "windowsName";
function a() {
var name = "Cherry";
console.log(this.name); // windowsName
console.log("inner:" + this); // inner: Window
}
a();
console.log("outer:" + this) // outer: Window
这个相信大家都知道为什么 log 的是 windowsName,因为根据刚刚的那句话“this 永远指向最后调用它的那个对象”,我们看最后调用 a
的地方 a();
,前面没有调用的对象那么就是全局对象 window,这就相当于是 window.a()
;
注意,这里我们没有使用严格模式,如果使用严格模式的话,全局对象就是 undefined
,那么就会报错 Uncaught TypeError: Cannot read property 'name' of undefined
。
例 2:
var name = "windowsName";
var a = {
name: "Cherry",
fn : function () {
console.log(this.name); // Cherry
}
}
a.fn();
在这个例子中,函数 fn 是对象 a 调用的,所以打印的值就是 a 中的 name 的值。
例 3:
var name = "windowsName";
var a = {
name: "Cherry",
fn : function () {
console.log(this.name); // Cherry
}
}
window.a.fn();
这里打印 Cherry 的原因也是因为刚刚那句话“this 永远指向最后调用它的那个对象”,最后调用它的对象仍然是对象 a。
例 4:
var name = "windowsName";
var a = {
// name: "Cherry",
fn : function () {
console.log(this.name); // undefined
}
}
window.a.fn();
这里为什么会打印 undefined
呢?这是因为正如刚刚所描述的那样,调用 fn 的是 a 对象,也就是说 fn 的内部的 this 是对象 a,而对象 a 中并没有对 name 进行定义,所以 log 的 this.name
的值是 undefined
。
这个例子还是说明了:this 永远指向最后调用它的那个对象,因为最后调用 fn 的对象是 a,所以就算 a 中没有 name 这个属性,也不会继续向上一个对象寻找 this.name
,而是直接输出 undefined
。
例 5:
var name = "windowsName";
var a = {
name : null,
// name: "Cherry",
fn : function () {
console.log(this.name); // windowsName
}
}
var f = a.fn;
f();
这里你可能会有疑问,为什么不是 Cherry
,这是因为虽然将 a 对象的 fn 方法赋值给变量 f 了,但是没有调用,再接着跟我念这一句话:“this 永远指向最后调用它的那个对象”,由于刚刚的 f 并没有调用,所以 fn()
最后仍然是被 window 调用的。所以 this 指向的也就是 window。
由以上五个例子我们可以看出,this 的指向并不是在创建的时候就可以确定的,在 es5 中,永远是this 永远指向最后调用它的那个对象。
例 6:
var name = "windowsName";
function fn() {
var name = 'Cherry';
innerFunction();
function innerFunction() {
console.log(this.name); // windowsName
}
}
fn()
怎么改变this的指向
- 使用 ES6 的箭头函数
- 在函数内部使用
_this = this
- 使用
apply
、call
、bind
- new 实例化一个对象
ES6中的箭头函数
ES6标准入门里面这么写
- 函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象。
- 不可以当作构造函数。也就是说,不可以使用new命令,否则会抛出一个错误。
- 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。
- 不可以使用yield命令,因此箭头函数不能用作Generator。
函数内部使用_this = this
var name = "windowsName"; var a = { name : "Cherry",
func1: function () {
console.log(this.name)
}, func2: function () {
var _this = this;
setTimeout( function() {
_this.func1()
},100);
}
}; a.func2() // Cherry
var _this = this;
,这里的 this
是调用 func2
的对象 a,为了防止在 func2
中的 setTimeout 被 window 调用而导致的在 setTimeout 中的 this 为 window。我们将 this(指向变量 a)
赋值给一个变量 _this
,这样,在 func2
中我们使用 _this
就是指向对象 a 了。使用apply,call,bind
详细例子可查看参考资料。这里我列举一下我的看法
apply
fun.apply(a,b);
a代表要fun函数在运行的时候指定的this值;
b代表要传入的数组或者类数组对象
call
fun.call(a[,b1[,b2[,......]]])
a代表fun函数在运行的时候指定的this值;
b代表要传入的若干个参数列表
bind
bind()方法创建一个新的函数,当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
跟call类似,只不过需要在后面加上一个();
例如:b.bind(a,1,2)()
ES5中的this的更多相关文章
- ES5中新增的Array方法详细说明
一.前言-索引 ES5中新增的不少东西,了解之对我们写JavaScript会有不少帮助,比如数组这块,我们可能就不需要去有板有眼地for循环了. ES5中新增了写数组方法,如下: forEach (j ...
- ES5中数组新增的方法说明
一.前言-索引 ES5中新增的不少东西,了解之对我们写JavaScript会有不少帮助,比如数组这块,我们可能就不需要去有板有眼地for循环了. ES5中新增了写数组方法,如forEach (js v ...
- 《JS权威指南学习总结--7.9 ES5中的数组方法》
内容要点: ES5中定义了9个新的数组方法来遍历.映射.过滤.检测.简化和搜索数组. 概述:首先,大多数方法的第一个参数接收一个函数,并且对数组的每个元素(或一个元素)调用一次该函数. 如果是稀疏数组 ...
- Es5中的类和静态方法 继承
Es5中的类和静态方法 继承(原型链继承.对象冒充继承.原型链+对象冒充组合继承) // es5里面的类 //1.最简单的类 // function Person(){ // this.name='张 ...
- Typescript 学习笔记四:回忆ES5 中的类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- ES6中的类继承和ES5中的继承模式详解
1.ES5中的继承模式 我们先看ES5中的继承. 既然要实现继承,首先我们得要有一个父类. Animal.prototype.eat = function(food) { console.log(th ...
- ES5中的类与继承
最近在重新复习TypeScript,看到类这块的时候自然会和ES5中的类写法进行对比加深印象. 发现ES5的类与继承一些细节还是挺多的,时间久了容易忘记,特此记录下. 首先是ES5的类定义,这没什么好 ...
- ES5中新增的forEach等新方法的一些使用声明
转载地址:http://www.zhangxinxu.com/wordpress/?p=3220 一.前言-索引 ES5中新增的不少东西,了解之对我们写JavaScript会有不少帮助,比如数组这块, ...
- ES6中。类与继承的方法,以及与ES5中的方法的对比
// 在ES5中,通常使用构造函数方法去实现类与继承 // 创建父类 function Father(name, age){ this.name = name; this.age = age; } F ...
随机推荐
- python面向对象封装案例2
封装 封装 是面向对象编程的一大特点 面向对象编程的 第一步 —— 将 属性 和 方法 封装 到一个抽象的 类 中 外界 使用 类 创建 对象,然后 让对象调用方法 对象方法的细节 都被 封装 在 类 ...
- C语言运算符优先级和结合性一览表
所谓优先级就是当一个表达式中有多个运算符时,先计算谁,后计算谁.这个其实我们在小学学算术的时候就学过,如1+4÷2. 但是C语言中的运算符已经远不止四则运算中的加减乘除了,还有其他很多运算符.当它们出 ...
- winform 多个datagridview 之间同步滚动
1.添加Scroll事件 2.注意需判断数据长度,避免溢出 private void dgYY_Scroll(object sender, ScrollEventArgs e) { ) { dgFee ...
- 03hive_DDL数据定义
一. DDL数据定义 创建数据库 1)create database db_hive; 2)避免要创建的数据库已经存在错误,增加 if not exists 判断. create database i ...
- 红帽RHCE培训-课程3笔记内容2
9 NFS 9.1 NFS基础 目标 .使用NFS将文件系统连接到客户端,并使用IP 地址控制访问 .使用NFS将文件系统连接到客户端,并使用kerberos 来控制访问 .配置用户名和密码控制访问的 ...
- Hyperledger Explorer
简介 Hyperledger Explorer is a simple, powerful, easy-to-use, well maintained, open source utility to ...
- 解决maven项目java中配置文件打包被忽略
pom.xml中添加以下配置 <build> <!--配置打包时不过滤非java文件开始 --> <!--说明,在进行模块化开发打jar包时,maven会将非java文件 ...
- zookeeper 源码(二) session 和 处理事务请求
问题 session 如何生成的?sessionId为什么不直接使用时间戳+单机名 sessionid 关闭的时候的逻辑,sessionid 的维护是由各节点还是leader ? 会话相关 sessi ...
- 【C语言】(数组方式)输出一组成绩中的最高分与最低分
两种不同方式获取最大值与最小值 代码1: #include <stdio.h> int main() { ], sum = , max, min; int i; printf(" ...
- c语言实现面向对象编程
1.通用校验器接口(validator.h) #ifndef VALIDATOR_H_INCLUDED #define VALIDATOR_H_INCLUDED #include<stdbool ...