彻底搞清JS中的this,construtor,prototype

KarenI81 8年前
   <h2>this定义</h2>    <ol>     <li> <p>this是对象</p> </li>     <li> <p>this依赖函数执行的上下文</p> </li>     <li> <p>this存在于函数中(函数调用的时候被隐式传入)</p> </li>    </ol>    <pre>  <code class="language-javascript">直接看例子:        alert(this); //在全局环境调用this, this指向window,  输出[Object window]            function Person(){           alert(this);      }          方式一:          Person(); // 全局环境用Person函数, this指向window,  输出[Object window]         方式二:        var obj = new Person(); //把Person当做构造函数, 实例化一个对象                               //此时this指向了obj, 不再指向window,  输出[Object object]              function Person(){          alert(this.name); //此时无法判断this的身份       }              Person(); //this在全局环境中被调用, this.name == window.name, 输出了窗口的名字       var obj = new Person(); //this在obj环境下被调用, this.name == obj.name, 由于name没被赋值, 所以输出undefined                     由此可以看出, 我们在阅读代码或者写代码时,看到某个函数中定义的this时, 还无法去判断那个this身份,必须找到它依赖执行的环境(对象)。       再回头看看this的定义,大家就清楚自然了。</code></pre>    <h2>再看constructor和prototype</h2>    <p>constructor是一个对象的属性,这个属性存在在此对象的prototype中, 指向此对象的构造函数。分析这句话</p>    <ol>     <li> <p>constructor是一个对象属性。</p> </li>     <li> <p>constructor在prototype中</p> </li>     <li> <p>constructor指向构造函数</p> </li>    </ol>    <pre>  <code class="language-javascript">例子1:        function Person(name, age){          this.name = name;          this.age = age;      }      Person.prototype.getName = function(){          alert(this.name);      }      Person.prototype.getAge = function(){          alert(this.age);      }      var obj = new Person();      alert(obj.constructor == Person);// true      此种方式定义的prototype, constructor是隐藏的, 默认指向Person        例子2:      function Person(name, age){          this.name = name;          this.age = age;      }      Person.prototype = {          getName: function(){             alert(this.name);          },          getAge: function(){             alert(this.age);          }      }      var obj = new Person();      alert(obj.constructor == Person);// false            为什么是false? 这种定义prototype, 是把prototype重写了, 覆盖了默认的constructor。      换句话说, 其实这种方式就是给属性重新赋值了, 所以导致默认的constructor被覆盖。      此时的obj.constructor将指向的是Object。            改写一下上面的:      Person.prototype = {          constructor: Person, //强制指向Person          getName: function(){             alert(this.name);          },          getAge: function(){             alert(this.age);          }      }      此时constructor就指向Person了。            prototype是一个函数属性, 此属性同时也是一个对象, 保存着对象实例所共有的属性和方法。            分析这句话:          1.prototype是函数属性, 只要是函数, 就有prototype属性. 而不管是构造函数还是普通函数.          2.prototype同时也是对象.          2.prototype放的是公共的东西, 包括属性和方法.                例子1.          function Person(name, age){              this.name = name;              this.age = age;          }                    //是函数就有prototype属性, 这个属性也是一个对象          Person.prototype = {              getName: function(){ //所有对象实例都共享                  return this.name;              },              getAge: function(){//所有对象实例都共享                  return this.age;              }          }                var obj = new Person('tom', 23);          obj.getName(); //'tom'          var obj2 = new Person('jack', 23);          obj2.getName(); //'jack'          obj.getName == obj2.getName; //true, 所有实例共享          Person.prototype.getName(); //当做普通函数属性, 根据this定义, 此时this指向的是Person.prototype, 所以返回undefined        以上就是this, constructor, prototype的定义和他们之间的关系. 可能还有些粗糙, 欢迎大家补充.        综合例子:            var Tinker = function(){          this.elements = [];            };          Tinker.fn = Tinker.prototype = {              constructor: Tinker,              extend: function(obj){                  var p;                  for(p in obj){                      this.constructor.prototype[p] = obj[p];//此处若看明白了, 那么前面的就理解了                  }              }                    }          Tinker.fn.extend({             get: function(){                  var length = arguments.length,                  i = 0;                 for(; i < length; i++){                     this.elements.push(document.getElementById(arguments[i])); //此处若看明白了, 那么前面的就理解了                 }                 return this;//此处若看明白了, 那么前面的就理解了             },             each: function(fn){                  var i = 0,                      length = this.elements.length;                  for(; i < length; i++){                      fn.call(this.elements[i], i, this.elements[i]);                  }                  return this;//此处若看明白了, 那么前面的就理解了             }                        });           这个例子其实很简单, 就是向一个对象原型添加方法.一个方法是get, 用于查找页面id. 一个是each, 用于对找到的id元素执行一个方法       //假设有id = 'data', id = 'message'     var obj = new Tinker();     obj.get('data', 'message').each(function(i, item){                  this.style.cssText = 'height:20px; background:#ff0000';          })</code></pre>    <p>来自: <a href="/misc/goto?guid=4959742194794135528" rel="nofollow,noindex">http://www.cnblogs.com/tinkbe...</a></p>