如何确定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 值的更多相关文章

  1. 深入理解JavaScript系列(19):求值策略(Evaluation strategy)

    介绍 本章,我们将讲解在ECMAScript向函数function传递参数的策略. 计算机科学里对这种策略一般称为“evaluation strategy”(大叔注:有的人说翻译成求值策略,有的人翻译 ...

  2. 深入理解JavaScript运行机制

    深入理解JavaScript运行机制 前言 本文是写作在给团队新人培训之际,所以其实本文的受众是对JavaScript的运行机制不了解或了解起来有困难的小伙伴.也就是说,其实真正的原理和本文阐述的并不 ...

  3. 深入理解javascript系列(4):立即调用的函数表达式

    本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...

  4. 深入理解JavaScript的闭包特性如何给循环中的对象添加事件

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  5. 深入理解javascript原型和闭包(1)——一切都是对象

    “一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的函数——typeof().typeo ...

  6. 深入理解javascript原型和闭包(3)——prototype原型

    既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(深入理解 ...

  7. 深入理解javascript原型和闭包(4)——隐式原型

    注意:本文不是javascript基础教程,如果你没有接触过原型的基本知识,应该先去了解一下,推荐看<javascript高级程序设计(第三版)>第6章:面向对象的程序设计. 上节已经提到 ...

  8. 深入理解javascript原型和闭包(5)——instanceof

    又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/ ...

  9. 深入理解javascript原型和闭包(8)——简述【执行上下文】上

    什么是“执行上下文”(也叫做“执行上下文环境”)?暂且不下定义,先看一段代码: 第一句报错,a未定义,很正常.第二句.第三句输出都是undefined,说明浏览器在执行console.log(a)时, ...

随机推荐

  1. EasyNetQ操作RabbitMQ(高级消息队列)

    RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件).写消息队列的时候用RabbitMQ比较好,但是写的时候需要自己封装下,自己的封装,就需要对RabbitM ...

  2. Oracle集群和灾备解决方案介绍

       Oracle本身有各种各样的解决方案,本文主要是对以下几种解决方案做一下简单的梳理. 1. Oracle Rac解决方案. Oracle Rac主要通过两台Oracle服务器来组件集群,提高Or ...

  3. 为什么Goroutine能有上百万个,Java线程却只能有上千个?

      作者|Russell Cohen   译者|张卫滨   本文通过 Java 和 Golang 在底层原理上的差异,分析了 Java 为什么只能创建数千个线程,而 Golang 可以有数百万的 Go ...

  4. Android BroadcastReceiver介绍 (转)

    原文地址:http://www.cnblogs.com/trinea/archive/2012/11/09/2763182.html 本文主要介绍BroadcastReceiver的概念.使用.生命周 ...

  5. QT应用程序 安装路径中文异常问题

    [1]QT 安装中文路径启动异常问题 最近在搞一个很简单的QT应用程序,开发环境VS2017 + QT5.9,线上异常报错:安装中文路径下启动崩溃~~~~ 最后,本地调试Debug版本,发现安装中文路 ...

  6. Http权威指南学习研究

    学习时间:                                   该学习:第六章  6.6小节   加油   185页 2017年5月15日15:13:00 今天任务: 看完前两章节: ...

  7. 【BZOJ3747】[POI2015]Kinoman 线段树

    [BZOJ3747][POI2015]Kinoman Description 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放映的是第 ...

  8. 【译】Stackoverflow:Java Servlet 工作原理问答

    导读 本文来自stackoverflow的问答,讨论了Java Servlet的工作机制,如何进行实例化.共享变量和多线程处理. 问题:Servlet 是如何工作的?Servlet 如何实例化.共享变 ...

  9. 安装Nginx 及使用

    1.下载 Nginx wget http://nginx.org/download/nginx-1.10.3.tar.gz   (稳定版) 2.提前下载好依赖包 openssl.zlib.pcre p ...

  10. Python map,reduce,filter,apply

    map(function, iterable, ...) map()函数接收两个参数,一个是函数,一个是可迭代的对象,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回. 基本等 ...