JavaScript构造函数详解:原理、注意事项与原型链修正

作者:闭包旅人

时间:2026-10-29

浏览:184

本文详细解析JavaScript构造函数的运行机制,包括new操作符的作用、返回值处理及this指向问题。重点探讨使用对象字面量重写原型对象时导致的constructor属性丢失问题,并提供手动重置constructor的解决方案,确保原型链完整性。

文章目录

构造函数基本原理

构造函数的主要作用是初始化实例对象,而对象的prototype属性则用于继承自另一个实例对象。

构造函数注意事项

在使用构造函数时,需要注意以下几个关键点:

1. 按照惯例,构造函数名称的首字母应当大写。

2. 构造函数本身并不显式返回任何值。当使用new操作符调用构造函数时,JavaScript引擎会自动创建指定类型的实例并返回该实例。此时,构造函数内部的this对象会被自动创建,其类型即为构造函数的类型。

3. 构造函数内部也可以显式调用return语句。如果返回的是一个对象,则该对象会替代新创建的实例被返回;如果返回的是原始类型值,则该返回值会被忽略,新创建的实例仍会被返回。


 function Person( name){
        this.name =name;
      }
       var p1=new Person('John');

这一行为等同于以下逻辑:


   function person(name ){
        Object obj =new Object();
        obj.name =name;
         return obj;
      }
       var p1= person("John");

4. 由于构造函数本质上也是函数,因此可以直接调用(不使用new)。此时返回值为undefined,且构造函数内部的this对象指向全局this对象(在浏览器中为window)。这意味着this.name实际上是在创建一个全局变量name。如果在严格模式下直接调用Person构造函数(不使用new),将会抛出错误。

 构造函数基本原理

5. 也可以在构造函数中使用Object.defineProperty()方法来初始化属性:


  function Person( name){
        Object.defineProperty(this, "name"{
          get :function(){
             return name;
          },
           set:function (newName){
            name =newName;
          },
          enumerable :true, //可枚举,默认为false
           configurable:true //可配置
         });
      }  
       var p1=new Person('John');

原型对象与方法定义

6. 在构造函数中利用原型对象(prototype)来定义方法。


 //比直接在构造函数中写的效率要高的多
       Person.prototype.sayName= function(){
         console.log(this.name);
      };

然而,当需要定义的方法较多时,开发者通常倾向于采用更简洁的方式:直接使用对象字面量来替换整个原型对象,示例如下:


 Person.prototype ={
        sayName :function(){
           console.log(this.name);
        },
        toString :function(){
           return "[Person "+ this.name+"]" ;
        }
      };

原型重写与constructor修正

这种方式非常流行,因为它避免了多次键入Person.prototype。但需要注意一个副作用:

构造函数基本原理

使用字面量形式重写原型对象会改变构造函数的constructor属性,使其指向Object而非Person。这是因为原型对象默认具有一个constructor属性,这是其他对象实例所不具备的。当函数被创建时,其prototype属性也被创建,且该原型对象的constructor属性指向该函数。当使用对象字面量重写原型对象时,其constructor属性将被重置为通用对象Object。为了避免这一问题,需要在重写原型对象时手动重置constructor,如下所示:


 Person.prototype ={
        constructor :Person,
        
        sayName :function(){
           console.log(this.name);
        },        
        toString :function(){
           return "[Person "+ this.name+"]" ;
        }
      };

再次进行测试验证:

p1.constructor===Person

true

p1.constructor===Object

false

p1 instanceof Person

true

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章