彻底搞清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>