理解javascript this 值
如何确定this的值
this值会被传递给所有函数,this的值是基于运行时调用函数的上下文。
例如:从全局作用域调用sayFoo函数时,this引用window对象
当它作为myObject的一种方法调用时,this引用myObject
var foo = "foo";
var myObject = { foo: "I am myObject.foo" };
var sayFoo = function () {
console.log(this.foo);
};
//给myObject设置一个sayFoo属性,并指向sayFoo函数
myObject.sayFoo = sayFoo;
myObject.sayFoo();//输出 I am myObject.foo
sayFoo(); //输出foo
在嵌套函数中用this关键字引用head对象
当在嵌套函数内部使用this时,在ES3中,this失去了方向,引用的是head对象
例如:func2和func3内部的this失去了方向,引用的不是myObject,而是head对象
当匿名函数在函数内部被调用时,匿名函数内的this值将是head对象
例如:
var foo = {
func1: function(bar) {
bar(); //输出window,而不是foo
console.log(this); //这里的this关键字是foo对象的一个引用
}
};
foo.func1(function() {
console.log(this);
});
当this值得宿主函数被封装在另外一个函数内部或在另一个函数的上下文中被调用时,this值将永远是对head对象的引用。
var myObject = {
func1: function() {
console.log(this); //输出myObject
var func2 = function() {
console.log(this); //输出window,从此处开始,this都是window对象了
var func3 = function () {
console.log(this);//输出window,即head对象
}();
}();
}
};
myObject.func1();
充分利用作用域链研究嵌套函数问题
可以简单的在父函数中使用作用域链来保留对this的引用,以便this值不
丢失。如下代码演示通过 that变量以及其作用域来有效的跟踪函数上下文:
//充分利用作用域链研究嵌套函数问题
var myObject = {
myProperty:"I can see the light",
myMethod: function() {
var that = this; //myMethod作用域内,保存this引用(也就是myObject)
var helperFunction = function() { //子函数
//输出通过作用域链得到“I can see the light”
console.log(that.myProperty);
console.log(this.myProperty);
console.log(this);
}();
}
};
myObject.myMethod();//调用myMethod
使用call()或apply()控制this值
this值通常取决于调用函数的上下文,但是我们可以使用apply()或call()来重写/控制this值
call()和apply()的区别在于函数传递参数的方式不同
如果使用call(),参数只是用逗号分隔的值
如果使用apply(),参数值以数组的形式传递。
例如如下:通过 call调用函数,以便使函数内部的this值将myObject作为它的上下文
//使用call()或apply()控制this值
var myObject = {};
var myFunction = function(parm1, parm2) {
//调用函数的时候,通过call()将this指向myObject
this.foo = parm1;
this.bar = parm2;
console.log(this);
};
myFunction.call(myObject, "foo", "bar");//调用函数,设置this值引用到myObject
console.log("foo=" + myObject.foo + ",bar=" + myObject.bar); //输foo=foo,bar=bar
改为直接调用的结果为:
var myObject = {};
var myFunction = function(parm1, parm2) {
//调用函数的时候,通过call()将this指向myObject
this.foo = parm1;
this.bar = parm2;
console.log(this);
};
myFunction("foo", "bar");//直接调用,this指向window
console.log("foo=" + myObject.foo + ",bar=" + myObject.bar);//foo=undefined,bar=undefined
console.log("foo=" + myFunction.foo + ",bar=" + myFunction.bar);//foo=undefined,bar=undefined
console.log("foo=" + foo + ",bar=" + bar);//foo=foo,bar=bar
在用户自定义构造函数内部使用this关键字
使用new关键字调用函数时,this值(在构造函数中声明的)引用实例本身。
例如:如下代码创建了Person构造函数,创建Person的实例时,this.name将引用新创建的对象。
var Person = function(name) {
this.name = name || "john doe";//this引用所创建的实例
};
var cody = new Person("Cody Lindley");//基于Person构造函数创建实例
console.log(cody.name);//输出Cody Lindley
使用new关键字调用构造函数时,this引用“即将创建的对象”
如果不使用new关键字,this值将是调用Person的上下文—在本例中是head对象
如下代码:
var Person2 = function (name) {
this.name = name || "john doe"; //this引用所创建的实例
};
var cody2 = Person2("Cody Lindley"); //基于Person构造函数创建实例
console.log(cody2.name); //报name不存在,实际上name值设置到了window.name上
console.log(window.name); //输出Cody Lindley
原型方法内的this关键字引用构造函数实例
当在添加至构造函数的prototype属性的函数中使用this时,this引用调用方法的实例:
例如:
//原型方法内的this关键字引用构造函数实例
var Person = function(x) {
if (x) {
this.fullName = x;
}
};
Person.prototype.whatIsMyName = function() {
return this.fullName;//this引用Person()所创建的实例上
};
var cody = new Person("cody lindley");
var lisa = new Person("lisa lindley");
//调用继承的whatIsMyName方法,该方法用this引用实例
console.log(cody.whatIsMyName(), lisa.whatIsMyName()); //输出cody lindley,lisa lindley
Object.prototype.fullName = "John Doe";
var john = new Person();
console.log(john.whatIsMyName());
当在prototype对象中的方法内部使用this关键字时,this可用于引用实例。如果该实例不包含所要查找的属性,则继续在原型上查找。
理解javascript this 值的更多相关文章
- 深入理解JavaScript系列(19):求值策略(Evaluation strategy)
介绍 本章,我们将讲解在ECMAScript向函数function传递参数的策略. 计算机科学里对这种策略一般称为“evaluation strategy”(大叔注:有的人说翻译成求值策略,有的人翻译 ...
- 深入理解JavaScript运行机制
深入理解JavaScript运行机制 前言 本文是写作在给团队新人培训之际,所以其实本文的受众是对JavaScript的运行机制不了解或了解起来有困难的小伙伴.也就是说,其实真正的原理和本文阐述的并不 ...
- 深入理解javascript系列(4):立即调用的函数表达式
本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...
- 深入理解JavaScript的闭包特性如何给循环中的对象添加事件
初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...
- 深入理解javascript原型和闭包(1)——一切都是对象
“一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的函数——typeof().typeo ...
- 深入理解javascript原型和闭包(3)——prototype原型
既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(深入理解 ...
- 深入理解javascript原型和闭包(4)——隐式原型
注意:本文不是javascript基础教程,如果你没有接触过原型的基本知识,应该先去了解一下,推荐看<javascript高级程序设计(第三版)>第6章:面向对象的程序设计. 上节已经提到 ...
- 深入理解javascript原型和闭包(5)——instanceof
又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/ ...
- 深入理解javascript原型和闭包(8)——简述【执行上下文】上
什么是“执行上下文”(也叫做“执行上下文环境”)?暂且不下定义,先看一段代码: 第一句报错,a未定义,很正常.第二句.第三句输出都是undefined,说明浏览器在执行console.log(a)时, ...
随机推荐
- 启动 ./spark-shell 命令报错
当使用./spark-shell 命令报错 Caused by: ERROR XJ040: Failed to start database @476fde05, see the next excep ...
- SpringBoot项目的云服务器部署
1.场景还原 springboot配置相当简单,人人皆知.怎么把springboot工程部署到云服务器上呢?可能有人会说,博主你前篇不是讲了java工程的云部署把:但是我想澄清一点的是,我前篇的工程都 ...
- 50 years of Computer Architecture: From the Mainframe CPU to the Domain-Specific TPU and the Open RISC-V Instruction Set
1.1960年代(大型机) IBM发明了具有二进制兼容性的ISA——System/360,可以兼容一系列的8到64位的硬件产品,而不必更换操作系统.这是通过微编程实现的,每个计算机模型都有各自的ISA ...
- C语言中的一个*和[]优先级问题
最近写着玩了这么一段代码 int Init(int **T, int v1, int v2, int v3) { *sizeof(int)))) exit(-); *T[]=v1, *T[]=v2, ...
- saltstack内置执行模块groupadd
groupadd模块用于命令行管理用户组 salt.modules.groupadd.add(name, gid=None, system=False) 添加一个用户到指定GID 例:salt '*' ...
- Linux时间时区详解与常用时间函数
时间与时区 整个地球分为二十四时区,每个时区都有自己的本地时间. Ø UTC时间 与 GMT时间 我们可以认为格林威治时间就是时间协调时间(GMT = UTC),格林威治时间和UTC时间都用秒数来计 ...
- CSS改变字体下划线颜色
下图是网页中一个非常普通的列表. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQXVndXMzMzQ0/font/5a6L5L2T/fontsize/40 ...
- Spring框架结构
在processOn思维导图上看的一个程序员写的,挺不错的,分享出来,便于学习和回顾.
- c/c++的一些小知识点2
- SDOI2012 Round1 day2 拯救小云公主(dis)解题报告
#include<cstdio> #include<cmath> #include<iostream> using namespace std; typedef l ...