理解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)时, ...
随机推荐
- Cassandra安装和初次使用
Cassandra安装和初次使用 卡珊德拉(Cassandra)又译卡桑德拉.卡珊卓,为希腊.罗马神话中特洛伊(Troy)的公主,阿波罗(Apollo)的祭司.因神蛇以舌为她洗耳或阿波罗的赐予而有预言 ...
- 并行编程(2) - sum.msic.Unsafe 二
整理了几个曾经从网上记录sum.msic.Unsafe类的演示样例.供大家參考: package com.fish.unsafe; import java.io.File; import java.i ...
- 由浅到深理解ROS(2)
ROS文件系统 用户可以直接参看官网:http://wiki.ros.org/ROS/Tutorials/NavigatingTheFilesystem ROS文件系统中的两个最基本的概念:Packa ...
- poj 2524 Ubiquitous Religions(并查集)
Ubiquitous Religions Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 23168 Accepted: ...
- 使用onepage-scroll全屏滚动插件时的注意事项
如果项目需要在移动端访问时需要设置responsiveFallback属性,并且在此之前还需要检测浏览器的级别(引入modernizr.js文件) var $responsiveFallback = ...
- VS2010 fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
VS2010在经历一些更新后,建立Win32 Console Project时会出“error LNK1123” 错误,解决方案为将 项目|项目属性|配置属性|清单工具|输入和输出|嵌入清单 “是”改 ...
- Conductors(水题)
Conductors Background Everyone making translations from English to Russian knows an English phrase & ...
- SpringBoot中的配置文件
http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
- 【python】-- 多进程的基本语法 、进程间数据交互与共享、进程锁和进程池的使用
多进程 进程之间是相互独立的,python是启动进程的时候,是启动的是原生进程.进程是没有GIL锁的,而且不存在锁的概念,进程之间的数据式不能共享的,而线程是可以的. 1.进程的定义 用mulipro ...
- Linux安装Nginx使用负载均衡
1.实验准备准备三台计算机 nginx1 192.168.13.121 作为nginx负载均衡器nginx2 192.168.13.24 web服务,提供一个页面 nginx3 192 ...