理解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可用于引用实例。如果该实例不包含所要查找的属性,则继续在原型上查找。

时间: 2024-08-27 23:01:13

理解javascript this 值的相关文章

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

介绍 本章,我们将讲解在ECMAScript向函数function传递参数的策略. 计算机科学里对这种策略一般称为“evaluation strategy”(大叔注:有的人说翻译成求值策略,有的人翻译成赋值策略,通看下面的内容,我觉得称为赋值策略更为恰当,anyway,标题还是写成大家容易理解的求值策略吧),例如在编程语言为求值或者计算表达式设置规则.向函数传递参数的策略是一个特殊的case. http://dmitrysoshnikov.com/ecmascript/chapter-8-eva

深入理解javascript闭包

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. Js代码 function

深入理解JavaScript中创建对象模式的演变(原型)

创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Object构造函数和对象字面量方法 工厂模式 自定义构造函数模式 原型模式 组合使用自定义构造函数模式和原型模式 动态原型模式.寄生构造函数模式.稳妥构造函数模式 第一部分:Object构造函数和对象字面量方法 我之前在博文<javascript中对象字面量的理解>中讲到过这两种方法,如何大家不熟悉,可以点进去看一看回顾一下.它们的优点是用来创建单个的对象非常方

深入理解JavaScript中的属性和特性

深入理解JavaScript中的属性和特性? JavaScript中属性和特性是完全不同的两个概念,这里我将根据自己所学,来深入理解JavaScript中的属性和特性. 主要内容如下: 理解JavaScript中理解对象的本质.理解对象与类的关系.对象与引用类型的关系 对象属性如何进行分类 属性中特性的理解 第一部分:理解JavaScript中理解对象的本质.理解对象与类的关系.对象与引用类型的关系 对象的本质:ECMA-262把对象定义为:无序属性的集合,其属性可以包含基本值.对象或者函数.即

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

原文来自http://www.cnblogs.com/wangfupeng1988/p/3977987.html 这是我非常感兴趣的东西,原型和闭包,当我看到标题后,我就迫不及待的点开了.今天我自己学习一下,顺便借花献佛,不理解的也可以再看一看. "一切都是对象"这句话的终点在于如何去理解"对象"这个概念.所谓Object,其实是所有对象的祖宗,这句话不难理解,而值的类型不是对象. 首先咱们还是看一看JavaScript中一个常用的函数 - typeof(). ty

彻底理解JavaScript原型

原型是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有"[[prototype]]"属性,函数对象有"prototype"属性,原型对象有"constructor"属性. 为了弄清原型,以及原型相关的这些属性关系,就有了这篇文章. 相信通过这篇文章一定能够清楚的认识到原型,现在就开始原型之旅吧. 认识原型 开始原型的介绍之前,首先来认识一下什么是原型? 在JavaScript中,原型也是一个对象,通过原型可以实现对象的属

深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点(转)

才华横溢的Stoyan Stefanov,在他写的由O’Reilly初版的新书<JavaScript Patterns>(JavaScript模式)中,我想要是为我们的读者贡献其摘要,那会是件很美妙的事情.具体一点就是编写高质量JavaScript的一些要素,例如避免全局变量,使用单变量声明,在循环中预缓存length(长度),遵循代码阅读,以及更多. 此摘要也包括一些与代码不太相关的习惯,但对整体代码的创建息息相关,包括撰写API文档.执行同行评审以及运行JSLint.这些习惯和最佳做法可以

深刻理解JavaScript基于原型的面向对象

主题一.原型 一.基于原型的语言的特点 1 只有对象,没有类;对象继承对象,而不是类继承类. 2  "原型对象"是基于原型语言的核心概念.原型对象是新对象的模板,它将自身的属性共享给新对象.一个对象不但可以享有自己创建时和运行时定义的属性,而且可以享有原型对象的属性. 3 除了语言原生的顶级对象,每一个对象都有自己的原型对象,所有对象构成一个树状的层级系统.root节点的顶层对象是一个语言原生的对象,其他所有对象都直接或间接继承它的属性. 显然,基于原型的语言比基于类的语言简单得多,我

全面理解Javascript中Promise

全面理解Javascript中Promise 最近在学习Promise的时候,在网上收集了一些资料,发现很多的知识点不够系统,所以小编特意为大家整理了一些自认为 比较好的文章,供大家更好地学习js中非常有趣的Promise Promise概念 2015 年 6 月,ECMAScript 6 的正式版 终于发布了. ECMAScript 是 JavaScript 语言的国际标准,javascript 是 ECMAScript 的实现.ES6 的目标,是使得 JavaScript 语言可以用来编写大