javascript this对象

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>this.html</title>
	
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">
    <meta name="keywords" content="keyword1,keyword2,keyword3">
    <meta name="description" content="this is my page">
    <meta name="content-type" content="text/html; charset=UTF-8">
    
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
    <script type="text/javascript" src="../js/jquery-1.11.3.js"></script>

  </head>
  
  <body>
	<div id="div"></div>
	<script type="text/javascript">
	// <![CDATA[
		//如果你需要在没有硬编码的window标识符下访问全局对象,你可以在任何层级的函数作用域中做如下操作:
		var global = (function () {
			return this;
		})();
		
		function show(str) {
			$("#div").append($("<p></p>").text("" + str));
		}

		//JavaScript 有一套完全不同于其它语言的对 this 的处理机制。 
		//在五种不同的情况下 ,this的指向各不相同。 
		//1、全局范围内:当在全局范围内使用 this,它将会指向全局对象global
		//浏览器中运行的 JavaScript 脚本,这个全局对象的属性是global.window = global
		show(global);	//[object Window]
		
		//2、直接调用函数:这里 this 会指向全局对象。 
		//ES5 注意: 在严格模式下(strict mode),不存在全局变量。 这种情况下 this 将会是 undefined。 
		//function声明时相当于为全局添加了一个类型为Function的属性global.funName = function() {}
		function Test(name) {
			this.name = name;
			this.getName = function() {
				return this.name;
			};
		}
		//这里相当于调用global.Test("jaeson"),this指向global,为global增加了两个成员变量。
		Test("jaeson");
		show(global.name);	//jaeson
		show(getName());	//jaeson
		
		//3、点号方法调用:指向调用函数的对象。
		//相当于声明了global.test1 = {name : "coolrice", getName : function() { return this.name; }}
		var test1 = new Test("coolrice");
		//这里this指向test1对象
		show(test1.getName());	//coolrice
		
		//4、调用构造函数:如果函数倾向于和 new 关键词一块使用,则我们称这个函数是构造函数。 在函数内部,this指向新创建的对象。
		//5、显式的设置 this:当使用 Function.prototype 上的 call 或者 apply 方法时,函数内的 this 将会被显式设置为函数调用的第一个参数。 
		function foo() {
			this.name = "foo";
			this.show = function() {
				show("foo.show=" + this.name);
			};
		}
		function bar() {
			this.name = "bar";
			this.show = function() {
				show("bar.show=" + this.name);
			};
		}
		
		var foo1 = new foo();
		var bar1 = new bar();
		//this指向foo1
		foo1.show();			//foo.show=foo
		//this指向foo1
		bar1.show.call(foo1);	//bar.show=foo
		
		//注意: 在对象的字面声明语法中,this 不能用来指向对象本身。 因此 var obj = {me: this} 中的 me 不会指向 obj,
		//因为 this 只可能出现在上述的五种情况中。这个例子中,如果是在浏览器中运行,obj.me 等于 global 对象。 
		var obj = {me: this};
		show(obj.me);	//[object Window]
		
		
		//常见误解:
		//尽管大部分的情况都说的过去,不过第二个规则(就是直接调用函数时,this 指向全局对象global)
		//被认为是JavaScript语言另一个错误设计的地方,因为它从来就没有实际的用途。 
		function TestMethod(name) {
			function method(name) {
				// this 将会被设置为全局对象(浏览器环境中也就是 window 对象)
				this.username = name;
			}
			method(name);				
		}
		TestMethod.prototype.username="value from prototype";
		TestMethod("chenzq");
		show(global.username);		//chenzq
		
		var testm = new TestMethod("jaesonchen");
		//从原型链中获得值
		show(testm.username ? testm.username : "undefined");	//value from prototype
		show(global.username);		//jaesonchen
		
		//一个常见的误解是 method 中的 this 将会指向 TestMethod 对象,实际上不是这样子的。 
		//为了在 method 中获取对 TestMethod 对象的引用,我们需要在 method 函数内部创建一个局部变量that指向 TestMethod 对象。 
		//that这个名字被广泛的用来指向外部的 this 对象。 在 闭包 中,经常可以看到 that 可以作为参数传递。
		function TestThat(name) {
			var that = this;
		  	function method(name) {
		    	// 使用 that 来指向 TestThat的对象
		    	that.namethat = name;
		  	}
		  	method(name);				
		}
		TestThat("name that");
		show(global.namethat);	//name that
		
		//这里this指向testt对象
		var testt = new TestThat("new that");
		show(testt.namethat);	//new that	
		show(global.namethat);	//name that
		
		//另一个看起来奇怪的地方是函数别名,也就是将一个方法赋值给一个变量。 
		function TestAlias(name) {
			this.aliasName = name;
			this.getAliasName = function() {
				return this.aliasName;
			};
		}
		var testa = new TestAlias("alias");
		show(testa.getAliasName());			//alias
		//相当于global.func = function() { return this.aliasName; }
		//func 就像一个普通的函数被调用;因此,函数内的 this 将不再被指向到 testa 对象,而是global对象。
		var func = testa.getAliasName;
		show(func());	//undefined
		
		//对于函数作为参数传递导致的this指针丢失的问题,目前很多框架都已经有方法解决了。
		//Prototype的解决方案——传参之前使用bind方法将函数封装起来,并返回封装后的对象
		function bind() {
    		if (arguments.length < 2 && arguments[0] === undefined) 
        		return this;
    		var __method = this, args = $A(arguments), object = args.shift();
   			return function(){
        		return __method.apply(object, args.concat($A(arguments)));
    		};
		}
		
	// ]]>
	</script>
  </body>
</html>

相关推荐