js中this详解
this对象是在闭包一节中提到的,书上的原话是:“this对象是在运行时基于函数的执行环境绑定的,在全局函数中,this等于window,而当函数作为某个对象的方法调用时,this等于那个对象,匿名函数的执行环境具有全局性,因此其this对象通常指向window。”也可以理解为this是指向函数所处作用域中的对象,决定this的就是当前的执行环境所在的作用域。
下面是this的四种常见情况下的用法:
1,纯函数调用,此时的this就是全局环境下的window,访问到的this对象的属性就是全局环境下定义的,而不是函数内部定义的。
var a = 1;
function fn(){
var a = 0;
console.log(this.a)
};
fn(); //
同样的,如果直接在函数里面定义this的属性,那么也就相当于在全局下定义了window的属性。
var a = 1;
function fn(){
this.a = 0;
}; console.log(a); // 1; fn(); console.log(a); // 0;
这里就直接覆盖掉了原先定义的a
2,作为对象的方法来调用,此时的this对象就是指向调用它的那个对象(上级对象,离他最近的那个)
var a = 0
function fn(){
console.log(this.a)
};
var obj = {
a: 1
};
obj.test = fn;
obj.test(); //
3,作为构造函数调用,this就是指向生成的新对象
function fn(){
this.a = 1
};
var o = new fn();
o.a; //
此时的this不指向window
var a = 0;
function fn(){
this.a = 1
};
var o = new fn();
o.a; //
a; //
此时并没有执行fn(),所以全局环境下的a没有改变
4,配合apply使用,此时的this就指向第一个参数,如果不传,就表示默认为全局环境
var x = 0;
function test(){
alert(this.x);
}
var o={};
o.x = 1;
o.m = test;
o.m.apply(); //0
o.m.apply(o); //
当this所在的函数还没被调用的时候,this的指向是不明确的,只有被调用的时候,this才会明确所指对象,指向的是调用这个函数的对象。
一,下面来看几个例子
function fn(){
user: "Yan",
console.log(this.user)
console.log(this);
}
fn();
// undefined
// window
其实上面等同于下面这个:
window.fn();
这里fn()是被window对象调用的,作用域是全局环境下,所以这里的this指向window,而user在全局下未被定义;
再看一个更清楚的
var o = {
user: 'Yan',
fn: function(){
console.log(this.user);
console.log(this);
}
};
o.fn();
// Yan
// {user: 'Yan', fn: f}
这里调用fn()的是o这个对象,所以此时的this指向o。
那如果是下面这种情况呢:
window.o.fn();
结果是跟上面那个一样,为什么呢?这里我们把最初的定义再说具体一点,
this对象始终指向的是直接调用它的对象,这个对象就是它的上一级,就是最终输出的时候,a.fn()就是a,b.fn()就是b。。。
下面这个例子也能很好的说明上面这段话:
var o = {
user: 'Yan',
a: {
user: 'Chen',
fn: function(){
console.log(this.user);
console.log(this);
}
}
};
o.a.fn();
// Chen
// {user: 'Chen', fn: f}
如果上面这个稍作改动,结果如何呢,来看:
var j = o.a;
j.fn();
答案是还是一样的,因为这里的fn()是被对象j调用的,而对象j是o.a的复制,引用类型的复制,所以fn()被调用的还是a,所以this依然指向a
但是下面这种情况就比较特殊了,来看:
var h = o.a.fn;
h();
// undefined
// window
为什么这里的指向不是a了,因为h相当于复制了fn这个方法,而此时h()就等同于window.h(),那么此时的this指向的就是它的调用对象window。
二,当this遇到构造函数的时候
这个又要另当别论了,直接先看代码:
function fn(){
this.user = 'Yan'
}
var a = new fn();
console.log(a.user);
// Yan
new关键字可以改变this的指向对象,这里的new创建了一个fn的实例a,相当于在a里面复制了一个fn,当执行a.user的时候,实际上就是指向的a,因为fn是a调用的。
三,当this遇到return的时候
先把结论说了,当return一个对象的时候(null除外),this指向的就是那个返回的对象,如果不是对象,指向的就还是原函数的实例。
function fn()
{
this.user = 'Yan';
return {
user: 'Chen'
}
}
var a = new fn;
console.log(a.user); // Chen
function fn()
{
this.user = 'Yan';
return function(){};
}
var a = new fn;
console.log(a.user); // undefined
null除外:
function fn()
{
this.user = 'Yan';
return null;
}
var a = new fn;
console.log(a.user); // Yan
不是对象的时候:
function fn()
{
this.user = 'Yan';
return 1;
}
var a = new fn;
console.log(a.user); // Yan
function fn()
{
this.user = 'Yan';
return undefined;
}
var a = new fn;
console.log(a.user); // Yan
==========================
2018年7月3日补充
当一个函数被调用时,会创建一个活动记录(有时候称为执行上下文),这个记录包含函数在哪里被调用(调用栈)、函数的调用方式以及传入的参数等信息,this就是这个记录的一个属性,会在函数执行的过程中用到。
this既不指向函数自身也不指向函数作用域,它是在函数被调用时绑定的,指向什么完全取决于函数在哪里被调用。
箭头函数本身没有this,取而代之的是当前的词法作用域覆盖了this本来的值。
js中this详解的更多相关文章
- js中eval详解,用Js的eval解析JSON中的注意点
先来说eval的用法,内容比较简单,熟悉的可以跳过eval函数接收一个参数s,如果s不是字符串,则直接返回s.否则执行s语句.如果s语句执行结果是一个值,则返回此值,否则返回undefined. 需要 ...
- js中arguments详解
在js中一切都是对象,连函数也是对象,函数名其实是引用函数定义对象的变量. 什么是arguments? 这个函数体内的arguments非常特殊,实际上是所在函数的一个内置类数组对象,可以用数组的[i ...
- Node.js中Async详解:流程控制
安装 npm install async --save 地址 https://github.com/caolan/async Async的内容主要分为三部分 流程控制: 简化九种常见的流程的处理 集合 ...
- js中apply详解
学习http://www.cnblogs.com/delin/archive/2010/06/17/1759695.html 1.对象的继承,一般的做法是复制:Object.extend protot ...
- Angular JS 中 指令详解
Angular JS的强大功能就在于其可以自定义很多指令,现在就指令做一下详细的剖析. 一个Angular js 指令(directive)需要指定一个唯一的名字(myDirective)和一个函数, ...
- js中eval详解
先来说eval的用法,内容比较简单,熟悉的可以跳过 eval函数接收一个参数s,如果s不是字符串,则直接返回s.否则执行s语句.如果s语句执行结果是一个值,则返回此值,否则返回undefined. ...
- 《Node.js开发实战详解》学习笔记
<Node.js开发实战详解>学习笔记 ——持续更新中 一.NodeJS设计模式 1 . 单例模式 顾名思义,单例就是保证一个类只有一个实例,实现的方法是,先判断实例是否存在,如果存在则直 ...
- Js apply 方法 详解
Js apply方法详解 我在一开始看到JavaScript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
- ES6,ES2105核心功能一览,js新特性详解
ES6,ES2105核心功能一览,js新特性详解 过去几年 JavaScript 发生了很大的变化.ES6(ECMAScript 6.ES2105)是 JavaScript 语言的新标准,2015 年 ...
随机推荐
- JDK1.8中的线程池
上面这段代码一直在用,面试的时候也经常被问到,却从未深究过,不知道线程池到底是怎么回事,今天看看源代码,一探其究竟 线程池主要控制的状态是ctl,它是一个原子的整数,其包含两个概念字段: worker ...
- mac安装mysql的两种方法(含配置)
1.使用安装包安装mysql 双击打开安装文件 双击pkg文件安装 一路向下,记得保存最后弹出框中的密码(它是你mysql root账号的密码) 正常情况下,安装成功. 此时只是安装成功,但还需要额外 ...
- Git-分布式版本控制系统(二)
工作区(Woring directory ) 版本区(repository,即隐藏的.git文件) Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git ...
- windows 纤程
纤程本质上也是线程,是多任务系统的一部分,纤程为一个线程准并行方式调用多个不同函数提供了一种可能,它本身可以作为一种轻量级的线程使用.它与线程在本质上没有区别,它也有上下文环境,纤程的上下文环境也是一 ...
- 解决打开png图片黑屏问题(批量还原Xcode优化后的png)
window 打开Xcode 里面的png图片会黑屏,但是在mac 打开就显示正常, 这是因为Xocde里面的png图片被 pngcrush 优化过了,需要还原它的优化,window 平台才可以打开. ...
- 腾讯windows系统服务器
今天用腾讯的服务器搭建起了自己的博客,先看主页效果...简单的ui设计,主要就是要上服务器看看. 说说服务器的搭建: 1.卖,进腾讯云,自己对应的买操作系统的就可以的啦.具体的链接: https ...
- ssh远程登录命令简单实例
ssh远程登录命令简单实例 ssh命令用于远程登录上Linux主机. 常用格式:ssh [-l login_name] [-p port] [user@]hostname 更详细的可以用ssh -h查 ...
- Js默认参数(多参数情况)
js function example(settings) { var defaultSetting = { name: '小红', age: '30', sex: '女', phone: '1008 ...
- Scrapy运行错误:ImportError: No module named win32api
需要安装pypiwin32,直接通过官网安装exe会出现很多错误,所以直接运行以下命令: pip install pypiwin32
- CSS清除浮动的几种方式
浮动对页面的影响: 如果一个父盒子中有一个子盒子,并且父盒子没有设置高,子盒子在父盒子中进行了浮动,那么将来父盒子的高度为0.由于父盒子的高度为0, 下面的元素会自动补位,所以这个时候要进行浮动的清除 ...