理解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)时, ... 
随机推荐
- 简易web服务器(java版)
			//直接使用 ServerSocket 监听服务器端口,就能实现web服务器package ThreadPoolTest; import java.io.InputStream; import jav ... 
- Junit内部解密之三: 单元测试用例运行的全过程
			转自:http://blog.sina.com.cn/s/blog_6cf812be0100x8sb.html 我们以一个非常简单的TestCalculator类为例,只有一个测试方法: Public ... 
- spring roo反向工程
			1.创建spring roo工程 2.在数据库中创建数据库feedback_schema,再创建几张表 3.创建连接数据库 persistence setup --provider HIBER ... 
- 【转】【Mac系统】之Python版本切换、谷歌浏览器取消自动升级
			都是很有用的文章,本文都是转载文章,以便后续查阅: Mac Chrome浏览器取消自动升级(看这一篇就够了) <Mac修改默认python版本> <mac设置python版本切换,和 ... 
- 网络流合集:bzoj1433,1934,1854 题解
			转载请注明:http://blog.csdn.net/jiangshibiao/article/details/23992205 网络流/二分图大合集 [NO.1*原题] 1433: [ZJOI200 ... 
- Laravel开发:多用户登录验证(2)
			上一篇讲了最基本的User验证,现在来讲一下Admin的验证. 先贴代码, 路由:routes/web.php加上以下代码, //... Route::get('admin/login', 'Admi ... 
- 设置tableView背景颜色
			[treeTableView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight] ... 
- .net EF监控 MiniProfiler
			1.从NuGet上下载所需要的包:MiniProfiler.mvc,MiniProfiler,MiniProfiler.ef 2.Global.asax 加入 protected void Appli ... 
- Ajax之基础总结
			一.Ajax 简介 Ajax 由 HTML.JavaScript技术.DHTML 和 DOM 组成,这一杰出的方法可以将笨拙的 Web 界面转化成交互性的 Ajax 应用程序.在详细探讨 Ajax 是 ... 
- Python小练习(持续更新....)
			最近一直在学习python,这些小练习有些是书上的,有些是别人博客上的! # 1.题目1# 给一个字符串,统计其中的数字.字母和其他类型字符的个数:# 比如输入“124mid-=”,输出:数字=3,字 ... 
