详解javascript中的this的指向问题
首先,要明白this 既不指向函数自身,也不指函数的词法作用域。this一般存在于函数中,表示当前函数的执行上下文,如果函数没有执行,那么this没有内容,只有函数在执行后this才有绑定。
然后,我们来看看this四种绑定规则,也可以说在四种不同函数执行方式时this的指向。
1.默认绑定(执行)
默认执行:即没有其他绑定规则存在时的默认规则。这也是函数调用中最常用的规则。this指向window,严格模式下指向undefined
function fn(){
console.log(this)
}
fn()
fn()
打印到控制台结果为window
开启严格模式后
function fn(){
"use strict"
console.log(this)
}
fn()
fn()
打印到控制台结果为undefined
2.隐式绑定(执行)
通过对象执行(通过上下文对象执行) obj.fn():当前的执行对象
function fn(){
console.log(this.a)
}
var a = 10;
var obj = {
a:20,
b:fn
}
var obj2 = {
a:30,
b:obj.b
}
obj2.b(); //??
obj2.b();
打印到控制台结果为30
因为obj2.b();
在上述代码中等价于obj2.fn()
,所以此时this指向obj2
,所以打印结果为30;
多层调用
function fn(){
console.log(this.a)
}
var a = 10;
var obj = {
a:20,
b:fn
}
var obj2 = {
a:30,
b:obj.b
}
var obj3 = {
a:40,
b:obj2
}
obj3.b.b() //?
obj3.b.b()
打印结果为30
上述代码调用结果为obj3.b->obj2,obj2.b->obj.b->fn
,因为this只获取最近一层调用的上下文对象,即obj2
,
所以结果为30
隐式丢失(函数别名)
注意:这里存在一个陷阱,大家在分析调用过程时,要特别小心
function fn() {
console.log( this.a );
}
var a = 2;
var obj = {
a: 3,
b: fn
};
var bar = obj.b;
bar(); //?
bar()
打印结果为2
为什么会这样,obj.b
赋值给bar,那调用bar()为什么没有触发隐式绑定,使用的是默认绑定呢。
这里有个概念要理解清楚,obj.b
是引用属性,赋值给bar的实际上就是fn
函数(即:bar指向fn
本身)。
那么,实际的调用关系是:通过bar找到fn
函数,进行调用。整个调用过程并没有obj的参数,所以是默认绑定,全局属性a。
隐士丢失(回调函数)
function fn(){
console.log(this.a)
}
var a=20;
var obj = {
a:20,
b:fn
}
setTimeout(obj.b, 2000);
function setTimeout(cb,t){
// t
cb() //?
}
cb()
打印结果为20
同样的道理,虽然参传是obj.fn
,因为是引用关系,所以传参实际上传的就是fn
对象本身的引用。对于setTimeout
的调用,还是 setTimeout
-> 获取参数中fn
的引用参数 -> 执行 fn
函数,中间没有obj的参与。这里依旧进行的是默认绑定。
3.显示绑定(执行)
function fn(){
console.log(this.a)
}
var obj1= {
a:10
}
var obj2 ={
a:20
}
var obj3 ={
a:30
}
fn.bind(obj1)();
fn.call(obj2);
fn.apply(obj3);
fn.bind(obj1)();
打印结果为10
fn.call(obj2);
打印结果为20
fn.apply(obj3);
打印结果为30
这里要注意fn.bind(obj1)
后面还要加一个括号才执行!
4.new 绑定(构造函数执行(通过new执行))
js中的new操作符,和其他语言中(如JAVA)的new机制是不一样的。js中,它就是一个普通函数调用,只是被new修饰了而已。
使用new来调用函数,会自动执行如下操作:
如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。
从这点可以看出,this指向的就是对象本身。
function foo(a) {
this.a = a;
}
var a = 2;
var bar1 = new foo(3);
console.log(bar1.a); // ?
var bar2 = new foo(4);
console.log(bar2.a); // ?
因为每次调用生成的是全新的对象,该对象又会自动绑定到this上,所以打印结果分别为3,4
绑定规则优先级
优先级是这样的,以按照下面的顺序来进行判断:
数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象。
数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this绑定的是 指定的对象。
数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上下文对象。
果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到 全局对象。
详解javascript中的this的指向问题的更多相关文章
- 【转】详解JavaScript中的this
ref:http://blog.jobbole.com/39305/ 来源:foocoder 详解JavaScript中的this JavaScript中的this总是让人迷惑,应该是js众所周知的坑 ...
- 详解javascript中的this对象
详解javascript中的this对象 前言 Javascript是一门基于对象的动态语言,也就是说,所有东西都是对象,一个很典型的例子就是函数也被视为普通的对象.Javascript可以通过一定的 ...
- (转载)详解Javascript中prototype属性(推荐)
在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不 ...
- 详解 javascript中offsetleft属性的用法(转)
详解 javascript中offsetleft属性的用法 转载 2015-11-11 投稿:mrr 我要评论 本章节通过代码实例介绍一下offsetleft属性的用法,需要的朋友可以做一 ...
- 详解JavaScript中的原型
前言 原型.原型链应该是被大多数前端er说烂的词,但是应该还有很多人不能完整的解释这两个内容,当然也包括我自己. 最早一篇原型链文章写于2019年07月,那个时候也是费了老大劲才理解到了七八成,到现在 ...
- 详解JavaScript中的Event Loop(事件循环)机制
前言 我们都知道,javascript从诞生之日起就是一门单线程的非阻塞的脚本语言.这是由其最初的用途来决定的:与浏览器交互. 单线程意味着,javascript代码在执行的任何时候,都只有一个主线程 ...
- 【转】详解JavaScript中的异常处理方法
有三种类型的编程错误:(1)语法错误和(2)运行时错误(3)逻辑错误:语法错误: 语法错误,也被称为解析错误,在编译时进行传统的编程语言,并出现在JavaScript解释时. 例如,下面一行将导致一个 ...
- 详解JavaScript中的arc的方法
今天说说JavaScript在网页中画圆的函数arc! 一.arc所需要的参数设置 1 arc(x, y, radius, startAngle, endAngle, counterclockwise ...
- 详解JavaScript中的this
JavaScript中的this总是让人迷惑,应该是js众所周知的坑之一. 个人也觉得js中的this不是一个好的设计,由于this晚绑定的特性,它可以是全局对象,当前对象,或者…有人甚至因为坑大而不 ...
随机推荐
- MYSQL主从复制、主主复制、双主多从配置
一.如何配置MYSQL的主从复制? 1. 两台数据库服务器,IP分别为 192.168.216.128 和 192.168.216.129,在服务器上装MYSQL(我的配置版本为5.5.56) 2. ...
- liunx基本操作操作与文件和目录的管理
一.基本操作 Tab键: 自动补全ctrl + u: 清空至行首ctrl + k: 清空至行尾 ctrl + l: 清屏 ctrl + c: 取消本次命令编辑重启:rebootsystemctl re ...
- 0 ElasticSearch
注意事项 需要jdk环境1.7以上 Elasticsearch Kibana 的下载地址统一为https://www.elastic.co/downloads/ 问题排查可以登录https://dis ...
- RabbitMQ搭建单机及集群
1,基本环境配置 hosts 文件 免密登录 2,访问官网 https://www.rabbitmq.com/download.html 3, 4,安装依赖 yum -y install make g ...
- 【iOS】stringWithFormat 保留小数点位数 float double
以前就见过,如下: text = [NSString stringWithFormat:@"%.1f", percentageCompleted]; 但一直没在意.刚一时好奇,查了 ...
- php 生成随机字符串,数字,大写字母,小写字母,特殊字符可以随意组合
* 生成随机字符串* @param int $length 要生成的随机字符串长度* @param string $type 随机码类型:0,数字+大小写字母:1,数字:2, ...
- MariaDB 修改存储路径后启动失败问题解决
修改 MariaDB 路径到 home 路径下, 执行 systemctl start mariadb 启动MariaDB 时,报错提示: Job for mariadb.service failed ...
- C# 在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级
//使用委托进行修改UI界面 if (this.InvokeRequired) { this.Invoke(new MethodInvoker(delegate { createList(); })) ...
- Vue项目中使用better-scroll
当 better-scroll 遇见 Vue 在我们日常的移动端项目开发中,处理滚动列表是再常见不过的需求了. 以滴滴为例,可以是这样竖向滚动的列表,如图所示: 也可以是横向滚动的导航栏,如图所示 ...
- laravel新项目报错 No application encryption key has been specified.
解决办法, 若文件根目录下没有 .env 1..env.example 改名使用命令 copy 修改为 .env 2.使用命令 php artisan key:generate 获取密码,自动保存到 ...