JS/JavaScript中 this 关键字对象详解
来源:互联网 发布:php 获取父类的属性 编辑:程序博客网 时间:2024/03/29 23:42
JS/JavaScript中 this 关键字对象详解
this是JavaScript中功能最强大的关键字之一。不幸的是,如果你不知道它具体怎么工作,你将很难正确使用它。
一、概述
this是面向对象语言中的一个重要概念,在JAVA,C#等大型语言中,this固定指向运行时的当前对象。但是在JavaScript中,由于JavaScript的动态性(解释执行,当然也有简单的预编译过程),this的指向在运行时才确定。这个特性在给我们带来迷惑的同时,也带来了编程上的自由和灵活,结合apply、call、bind方法,可以使JS变得异常强大。this是Javascript语言的一个关键字,它代表函数运行时自动生成的一个内部对象,只能在函数内部使用。
先看下面一段简单的代码:
<script type="text/javascript">
var name = "javascript";var obj = {name:'chunlynn',foo: function(){console.log(this.name);}}obj.foo(); //output:chunlynn//这里obj对象调用它的foo()函数,所以this指的是obj对象
</script>
问题1:obj是JavaScript中的什么类型?(想一想再往下看)
答案为:obj是js中的对象类型(Object类型)。对象就是一些属性和方法的集合。
问题2:如果执行obj.foo(),会在控制台输出什么呢?
答案为:chunlynn。
通过上面的这个小例子简单的认识下this:this是JS对象中的一个特殊指针,它的指向根据环境不同而会发生改变。
再来看下面一段简单的代码:
<script type="text/javascript">function doSomething(){
var name = "chunlynn";function doSomething(){var name = "linda";console.log(this.name);}console.log(window.doSomething);//打印doSomething函数代码,证明了doSomething是属于window的window.doSomething(); //输出:chunlynn。证明了doSomething是属于window的,this指向全局对象windowdoSomething();//输出:chunlynn 。因为的owner是window
this.doSomething();//输出:chunlynn 。this引用全局对象window,这个this一般是省略的.
</script>
查看chrome浏览器控制台的输出结果:
对于doSomething()这个函数:
这个函数是全局函数,这种全局函数实际上是属于window的(可以通过window.doSomething来访问),如果直接调用,那么根据 “this always refers to the “owner” of the function we're executing”,那么函数中的this就是window对象,window对象为全局对象,全局对象的属性name,就是全局变量,结果为:”chunlynn";
在JavaScript中,this通常指向的是我们正在执行的函数本身(注:用owner代表this所指向的内容),或者是,指向该函数所属的对象。当我们在页面中定义了函数doSomething()的时候,它的owner是页面,或者是JavaScript中的window对象(或 global对象,即全局对象, 在浏览器环境下,全局对象指的就是window对象)。对于一个onclick属性,它为它所属的HTML元素所拥有,this应该指向该HTML元素。
关于全局对象的概念与说明:
① JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。在浏览器 JavaScript 中,通常 window 是全局对象。
② 全局对象是预定义的对象,作为 JavaScript 的全局函数和全局属性的占位符。通过使用全局对象,可以访问所有其他所有预定义的对象、函数和属性。全局对象不是任何对象的属性,所以它没有名称。
③ 在顶层 JavaScript 代码中,可以用关键字 this 引用全局对象。但通常不必用这种方式引用全局对象,因为全局对象是作用域链的头,这意味着所有非限定性的变量和函数名都会作为该对象的属性来查询。例如,当JavaScript 代码引用 parseInt() 函数时,它引用的是全局对象的 parseInt 属性。全局对象是作用域链的头,还意味着在顶层 JavaScript 代码中声明的所有变量都将成为全局对象的属性。
④全局对象只是一个对象,而不是类。既没有构造函数,也无法实例化一个新的全局对象。
⑤ 在客户端 JavaScript 中,全局对象就是 Window 对象,表示允许 JavaScript 代码的 Web 浏览器窗口。
global对象通俗化理解:
⑥ 《JavaScript高级程序设计》中谈到,global对象可以说是ECMAScript中最特别的一个对象了,因为不管你从什么角度上看,这个对象都是不存在的。从某种意义上讲,它是一个终极的“兜底儿对象”,换句话说呢,就是不属于任何其他对象的属性和方法,最终都是它的属性和方法。我理解为,这个global对象呢,就是整个JS的“老祖宗”,找不到归属的那些“子子孙孙”都可以到它这里来认祖归宗。所有在全局作用域中定义的属性和函数,都是global对象的属性和方法,比如isNaN()、parseInt()以及parseFloat()等,实际都是它的方法;还有就是常见的一些特殊值,如:NaN、undefined等都是它的属性,以及一些构造函数Object、Array等也都是它的方法。总之,记住一点:global对象就是“老祖宗”,所有找不到归属的就都是它的。
二、this指向用法分类详解
先下个结论:谁调用或者哪个对象调用this所在的函数,this就指向谁。
① 对象构造函数中的this
作为对象使用时this指向当前对象。
<script type="text/javascript">var name = "chunlynn";//构造函数function Foo (){this.name = 'linda';this.foo = function(){console.log(this.name);}}// 实例化对象var obj = new Foo();obj.foo(); //output:linda// this指向:谁调用或者哪个对象调用this所在的函数,this就指向谁。//这里是Foo的实例化对象obj调用的foo()函数,所以this指向是Foo对象。</script>
注意构造函数和普通函数的区别,构造的属性用this.name="chunlynn",普通函数用var name = 'linda'。构造函数函数名称大写。
② 普通函数中的this
作为普通函数直接调用时,this指向window对象.
<script type="text/javascript">var name = "chunlynn";//普通函数function foo(){var name = 'linda';console.log(this.name);}foo(); //output:chunlynn// this指向:谁调用或者哪个对象调用this所在的函数,this就指向谁。//这里是window调用的foo()函数,所以this指的是实例window对象,this.name指的就是chunlynn</script>
下面再来看一个有些难度的:
<script type="text/javascript">var name = "chunlynn";//构造函数function Foo (){this.name = 'linda';this.foo = function(){var name = 'doudou';return function(){console.log(this.name);};}}// 实例化对象var obj = new Foo();obj.foo()(); //output:chunlynn// this指向:谁调用或者哪个对象调用this所在的函数,this就指向谁。// obj.foo()();拆开分步执行如下:// var re = obj.foo();// re(); ---> window.re();// 这里是window调用的foo()函数,所以this指向window对象, this.name指的就是chunlynn</script>
上面例子中的obj.foo()(); 也可以拆开了写成这样:
var re = obj.foo();
re(); ====> window.re();
写成这样是不是更利于理解了呢。
③ onclick(this)中的this指向
对于一个onclick属性,它为它所属的HTML元素所拥有,this指向该HTML元素。
例子:
<a href="javascript:void(0);" title="这个是一个标题!!" onclick="test(this);">A标签测试</a><script type="text/javascript">function test(obj){var value = obj.title;console.log(value); //这是一个标题!!}</script>
onclick为它所属的<a>元素所有,this指向<a>元素。
④ 定时器中的this指向
定时器中的this指的是window对象。
先来看一个定时器的例子:
<script type="text/javascript">var name = "chunlynn";//普通函数function foo(){var name = 'linda';console.log(this.name);}setTimeout(foo,5000); //output:chunlynn// this指向:谁调用或者哪个对象调用this所在的函数,this就指向谁。//这里要记住一点,定时器中的this指的是window对象。</script>
this的指向面试实例
<script type="text/javascript">var name = "chunlynn";var obj = {name:'linda',fn: function(){console.log(this.name);},foo:function(){setTimeout(this.fn,5000);}}obj.foo(); //output:chunlynn// this指向:谁调用或者哪个对象调用this所在的函数,this就指向谁。// 这里要记住一点,定时器中的this指的是window对象。</script>
分析:obj.foo()调用的是obj对象中的foo()方法;foo()方法里有一个定时器,定时器的一个参数是this.fn,这里的this指的是obj对象;然后fn()方法里又调用了this.name,但是大家还记得定时器中的this指的是window对象吧,所以最终this.name调用的是window对象中的name。
⑤ 使用apply、call 或 bind 方法时this的指向
使用apply 或者call方法时,this指向所传递的对象。
<script type="text/javascript"></script>var name = "chunlynn";var obj = {name:'linda',foo:function(){console.log(this.name);}}var f = {};f.name = "doudou";f.fun = obj.foo; //将obj对象的foo函数赋值给f对象的fun属性。本质为复制。f.fun(); //output:doudouf.fun.apply(obj); //output:lindaf.fun.apply(window); //output:doudouf.fun.apply(); //output:chunlynn// this指向:谁调用或者哪个对象调用this所在的函数,this就指向谁。
apply()的参数为空时,默认调用全局对象window。因此,这时的运行结果为0,证明this指的是全局对象window。
查看chrome浏览器控制台:
⑥ ES6 箭头函数和 this
箭头函数的特征就是:定义在哪,this 就指向那。
//es6中的双箭头操作符,类似于java中的lamada表达式<script type="text/javascript">var author = "chunlynn";var book = {name: 'linda',init: function(){setTimeout(ev=>{console.log(this.name);},3000);}}book.init(); //output:linda// this指向:谁调用或者哪个对象调用this所在的函数,this就指向谁。</script>
箭头函数的特征就是:定义在哪,this 就指向那。即箭头函数定义在一个对象里,那箭头函数里的 this 就指向该对象。
三、总结
① 谁调用或者哪个对象调用 this所在的函数,this就指向谁。
② “this” always refers to the “owner” of the function we're executing。
③ this通常指向的是我们正在执行的函数本身,或者是,指向该函数所属的对象。
④ this是Javascript语言的一个关键字,它代表函数运行时自动生成的一个内部对象,只能在函数内部使用。
相信能看到最后的各位,对于JavaScript中的有关this的坑都能跳出来的~~~。
阅读全文