JS类中定义原型方法的两种实现的区别

作者:半夏时间:2026-10-29 21:46:13浏览:109

本文探讨JavaScript中为类添加原型方法的两种常见方式:直接赋值函数对象与使用函数声明语法。通过分析脚本解析器的初始化优先级,指出函数声明具有最高优先级,而赋值语句仅在运行时执行。这导致在类定义顺序上,使用函数声明定义原型方法可能因解析顺序问题引发错误,而直接赋值则依赖运行时上下文,两者在行为机制上存在本质区别。

原型方法定义的两种常见方式

为JavaScript类添加原型(prototype)方法通常十分简便。在实际开发中,主要有两种常见的实现方式,但这两种方式在具体的使用场景和底层机制上是否存在差异呢?



JScript Class:


function JSClass()


 {

 }

Extends prototype method:


JSClass.prototype.MethodA = function()


 {

 };

Or



function = JSClass.prototype.MethodA()


 {

 };

为了更清晰地讨论这两种原型定义方式,我们可以将其简化为两个独立的函数进行对比,如下所示:


Foo1();



function Foo1()


  { 

alert('This is Foo1.');


  }

和 Foo2();


var Foo2 = function()


  { 

alert('This is Foo2.');


  }

函数声明与赋值表达式的执行优先级差异

执行第一个调用显然不会报错,但执行第二个调用时会出现问题,系统会提示:Microsoft JScript runtime error: Object expected。这表明函数定义(Foo1)在脚本解析阶段拥有最高的初始化优先级,这是合乎逻辑的。如果不优先处理函数定义,那么函数内部的调用将无法被正确处理。例如,若先定义fn1()再定义fn2(),却在fn1中调用fn2,解析过程将会失败。为什么Foo2无法被初始化?因为Foo2的定义并非函数声明,而是一条标准的赋值语句。它之所以能像标准函数一样被调用(Foo2()),完全是因为变量Foo2指向了一个函数对象的实例。


原型方法在类定义中的实际表现

再看原型方法导入的两种不同方式,原理便一目了然。由于执行优先级的不同,它们在实际使用中也表现出差异。请看以下示例:


<script language="javascript">


function NormalClass()


{ 

this.m_Property1 = 'P1 in Normal Class.';


this.m_Property2 = 'P2 in Normal Class.';



this.toString = function()


    { 

return '[class NormalClass]';


    }

return new InnerClass();



function InnerClass()


    { 

this.m_Property1 = 'P1 in Inner Class.';


this.m_Property2 = 'P2 in Inner Class.';



this.toString = function()


         { 

return '[class InnerClass]';


         }     
    }

InnerClass.prototype.Method1 = function()


    { 

alert(this.m_Property1);


    }; 

function InnerClass.prototype.Method2()


    { 

alert(this.m_Property2);


    };   
}

</script>



执行:


var nc = new NormalClass();


nc.Method1();


nc.Method2();



最终效果如何?原因是什么?

作者最新文章