`
zbm2001
  • 浏览: 16269 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

谈谈javascript原型构造机制

阅读更多
话题源于:js一个很奇怪的问题

ecma太拙嘴饶舌,本文力图用简单的测试示例来说明问题

任意创建一个函数,其原型prototype立刻被自动创建:
function Coo(){};
alert(Coo.prototype.constructor); //=>function Coo(){}


实例化Coo的原型prototype被置于作用域scope的最顶端:
function Coo(){
	alert(Coo.prototype.constructor);
}
var c1 = new Coo();  // => function Coo(){ ..}


在实例化Coo之前修改其原型prototype,其作用域scope顶端自动调整为修改后的原型prototype,并且实例c1可沿原型链找到method方法
function Coo(){
	alert(Coo.prototype.method); // => function(){} 作用域scope顶端自动调整为修改后的原型prototyp
}
Coo.prototype = { method : function(){} }
var c1 = new Coo();  // => function(){}
alert(c1.method);  // => function(){}


在实例化过程内部重新设置Coo的属性prototype:
function Coo(){
	alert(Coo.prototype.method); // => undefined 作用域scope顶端依旧为默认自动创建的原型prototype
	Coo.prototype = { method : function(){} } 
//注意:上面这行重新设置了Coo的[b]属性[/b]prototype,
//它已不再是Coo自动创建或是自动调整后的原型prototype了——这正是javascript原型机制的核心
}
var c1 = new Coo();  // => function(){}
//所以,虽然貌似:
alert(c1.prototype.method) // => function(){}
//但此[b]属性[/b]——"prototype"(),已非彼[b]原型[/b]——"prototype"了:
alert(c1.method); // => undefined


所以在实例化过程内部,只能基于原型prototype来扩展或修改方法
function Coo(){
	alert(Coo.prototype.method); // => undefined
	Coo.prototype.method = function(){}; // 在正宗原型prototype上扩展,非山寨! 
}
var c1 = new Coo();  // => function(){}
alert(c1.prototype.method); // => function(){}
alert(c1.method); // => function(){};


盘根究底,既然在实例化过程内部重新设置Coo的属性prototype,
那么Coo的原型prototype又会去了哪儿呢?
function Coo(){ 
    Coo.prototype = { method : function(){ alert("实例化中");} };
};
Coo.prototype = { constructor : Coo, method : function(){} }
var c1 = new Coo();
alert(c1.prototype.method); // => function(){ alert("实例化中");} 糟糕!
alert(c1.method); // => function(){} 谢天谢地!
alert(c1.constructor === Coo ); // => true; 原型链都还在,但它们似乎只是在内部被保存起来了


啰嗦了一大堆,简而言之:
函数的原型prototype是在实例化(或执行函数自身)之前就被自动创建(可以被修改或重置引用)的。
而在实例化(或执行函数自身)过程中,重置的prototype已沦为一个普普通通的对象属性了,
但是他却并不会干扰正常的javascript实例方法的原型链查找机制。



分享到:
评论
4 楼 picori 2010-03-01  
<pre name="code" class="js">   var CooGlobal;
   function Coo(){
   Coo.prototype = { method : function(){ alert("实例化中");} }; 
   CooGlobal = Coo;
   }; 
   var c1 = new Coo(); 
   console.log(c1.__proto__.method); //undefined 
   var gcoo  = new CooGlobal();
   console.log(gcoo.__proto__.method); //function()
   var c2 = new Coo();
   console.log(c2.__proto__.method);//function()</pre>
 
<p>我认为应该是在对象实例化的时候改变了Coo类的定义,把Coo指向了一个新类,并不是什么沦为一个普普通通的对象属性</p>
<p> </p>
3 楼 clone168 2009-08-20  
<p>
</p>
<div class="quote_title">zbm2001  写道</div>
<div class="quote_div">盘根究底,既然在实例化过程内部重新设置Coo的属性prototype, <br>那么Coo的原型prototype又会去了哪儿呢? <br>Js代码 <br>function Coo(){   <br>    Coo.prototype = { method : function(){ alert("实例化中");} };  <br>};  <br>Coo.prototype = { constructor : Coo, method : function(){} }  <br>var c1 = new Coo();  <br>alert(c1.prototype.method); // =&gt; function(){ alert("实例化中");} 糟糕!  <br>alert(c1.method); // =&gt; function(){} 谢天谢地!  <br>alert(c1.constructor === Coo ); // =&gt; true; 原型链都还在,但它们似乎只是在内部被保存起来了  <br><br><br>啰嗦了一大堆,简而言之: <br>函数的原型prototype是在实例化(或执行函数自身)之前就被自动创建(可以被修改或重置引用)的。 <br>而在实例化(或执行函数自身)过程中,重置的prototype已沦为一个普普通通的对象属性了, <br>但是他却并不会干扰正常的javascript实例方法的原型链查找机制。 </div>

<p> <br>不过楼主这个地方:</p>
<p>alert(c1.prototype.method); // =&gt; function(){ alert("实例化中");} 糟糕! </p>
<p>的注释貌似不对哈<br></p>
<p> </p>
2 楼 clone168 2009-08-20  
<div class="quote_title">zbm2001 写道</div>
<div class="quote_div">话题源于:<a href="http://clone168.iteye.com/blog/452290" target="_blank">js一个很奇怪的问题</a><br><br>啰嗦了一大堆,简而言之:<br>函数的原型prototype是在实例化(或执行函数自身)之前就被自动创建(可以被修改或重置引用)的。<br>而在实例化(或执行函数自身)过程中,<strong>重置</strong>的prototype已沦为一个普普通通的对象属性了,<br>但是他却并不会干扰正常的javascript实例方法的原型链查找机制。<br><br>
</div>
<p>楼主总结的还是比较简明易懂,例子也挺不错,再一次证明了javaeye很多牛人,这个问题也总算告一阶段了<img src="/images/smiles/icon_smile.gif" alt=""></p>
1 楼 lifesinger 2009-08-20  
zbm2001 写道

实例化Coo的原型prototype被置于作用域scope的最顶端:
function Coo(){
	alert(Coo.prototype.constructor);
}
var c1 = new Coo();  // => function Coo(){ ..}



这个说法不严谨,Coo.prototype 是在 parse 阶段就已添加,而不是 runtime 时才添加。

比如:
function Coo(){ }
debugger


在 firebug 下,debugger 处已经可以看到 Coo.prototype 为 Object

相关推荐

    图文详解JavaScript的原型对象及原型链

    JavaScript的原型对象和原型链是理解JavaScript继承机制的关键概念。首先,我们来区分两个关键的属性:`prototype`和`__proto__`。 1. `prototype`:主要用于构造函数,它是构造函数的一个属性,用于定义实例对象将...

    【JavaScript源代码】简单谈谈JavaScript寄生式组合继承.docx

    在JavaScript中,对象继承机制是一种非常重要的设计模式。常见的继承方式包括原型链继承、构造函数继承等。今天我们要探讨的是寄生式组合继承——一种结合了原型链继承和构造函数继承优点的模式。 #### 二、原型链...

    谈谈我对JavaScript原型和闭包系列理解(随手笔记9)

    原型链是JavaScript实现继承的一种机制。 每个对象都有一个内置的属性`[[Prototype]]`,它指向其原型对象。ES6中引入了`Object.getPrototypeOf`方法和`Object.setPrototypeOf`方法来获取和设置对象的原型。通过原型...

    简单谈谈javascript代码复用模式

    在探讨JavaScript代码复用模式时,首先需要了解代码复用的原则,以及JavaScript中对象的创建和继承机制。在软件工程中,代码复用是一种提高开发效率、降低软件维护成本的有效方式。GoF(设计模式的四位作者,即Erich...

    javascript权威指南电子书及全套源码

    首先,我们来谈谈JavaScript的基础知识。JavaScript是一种脚本语言,主要用于网页和网络应用的开发。它的主要特点是动态类型、基于原型的对象和函数作为一等公民。在JavaScript中,变量的数据类型可以在运行时改变,...

    深入理解JavaScript编程中的原型概念

    在JavaScript中,原型指的是一个对象从其他对象继承属性的机制。每个对象都有一个原型,原型本身也是对象,并且每个原型自身也有一个原型。这个链状结构被称为原型链,原型链的顶端是默认的对象原型,也是整个原型链...

    简单谈谈javascript高级特性

    首先,文章介绍了JavaScript中没有class的概念,而是通过function来模拟类的行为,这正是JavaScript语言的原型继承机制的体现。 紧接着,文章讨论了惰性载入函数的概念。惰性载入是一种性能优化技术,允许函数在第...

    谈谈JavaScript的New关键字

    通过原型链机制,实例对象能够访问构造函数原型上的属性和方法,实现了属性和方法的继承。理解`new`关键字的工作原理对于深入学习JavaScript至关重要,因为它涉及到对象创建、原型链、作用域以及继承等核心概念。

    javascript教程,帮助文档API

    接下来,让我们谈谈JavaScript的对象和原型。JavaScript的继承机制基于原型链,通过对象的__proto__属性和构造函数的prototype属性实现。理解原型和原型链可以帮助我们更好地实现面向对象编程,创建可复用的代码模块...

    javascript源码

    接着,我们谈谈JavaScript的核心概念——函数。函数是可重复使用的代码块,可以接受参数并返回值。JavaScript中的函数不仅可以作为值传递,还可以作为其他函数的参数,这是其函数式编程特性的一个体现。此外,...

    韩顺平javascript笔记(最全整理 dom编程 oop 基础语法)

    在韩顺平老师的笔记中,"JS 面向(基于)对象编程.doc"可能详细讲解了JavaScript中的类、构造函数、原型链、继承和封装等面向对象的高级主题;"dom编程.doc"则可能涵盖了常见的DOM操作方法、事件处理和性能优化策略...

    谈谈JavaScript中function多重理解

    这有两种主要方式:一是通过原型链,例如`Tab.prototype.getNav`,二是直接在构造器内部的`this`上定义方法,如`this.getNav = function() {...}`。另外,直接创建对象字面量时,也可以将函数作为对象的属性,如`var...

    retroSnaker:构造函数原型链结合sea.js贪吃蛇游戏

    JavaScript的原型(prototype)机制允许对象共享属性和方法。每个函数都有一个`prototype`属性,这个属性的`__proto__`指向构造函数的原型。当试图访问一个对象的属性时,如果该对象本身没有这个属性,JavaScript会...

    黑鹰JavaScript教训教程02

    我们可以通过构造函数和原型链实现类和继承的概念。例如: ```javascript function Person(name) { this.name = name; } Person.prototype.greet = function() { console.log("你好,我是" + this.name); } var ...

Global site tag (gtag.js) - Google Analytics