JavaScript中的对象与构造器

本文深入探讨JavaScript中对象的概念及其实现原理,包括构造器的定义与使用、对象属性的读取与修改机制等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、对象从何而来

首先来看什么是对象,搜索wiki百科可以得到解释,在面向对象(Object Oriented) 的软件中,对象(Object)是某一个(Class)的实例(Instance) ,因此说有对象之前必须先有类型,然后再将类型实例化就得到了对象。

那么在JavaScript中,类型不是通过如java的声明的方式定义,而是通过function的方式获得的,如

   1:  function DemoClass(){}
   2:   
   3:  var x = new DemoClass();

注意:这个顺序不能改变,必须先有function才能获得对象,否则会出现脚本错误,这是因为JavaScript的解析器是按顺序解析的,如果使用了还未被解析的function就会出现错误,由于这类function用来构造对象,把这类function叫做构造器

二、构造器的结构

每个构造器都有prototype属性,这个属性的结构是字典,可以任意添加名-值对组合,如

   1:  function DemoClass(){}
   2:   
   3:  DemoClass.prototype.Name = "DemoClass";
   4:   
   5:  DemoClass.prototype.IsNum = function(){return ture;};

同时每个构造器的prototype属性都有一个constructor属性指向构造器自身,构造器的prototype的类型为Object

三、对象的结构

每个对象都有__proto__只读属性,这个属性指向构造器的prototype属性。

除此之外,对象还有一个隐藏的内部属性,这个属性结构也是字典,可以任意添加名-值对组合 (例如:直接在构造函数中声明this.id;或者this.id=3;)

function DemoClass(){
 this.id;
}
var x = new DemoClass();                   // x.id=undefined
var y = new DemoClass();                   // y.id=undefined
DemoClass.prototype.id = "DemoClass1";     // x.id=DemoClass1,y.id=DemoClass1
x.id = "DemoClass2";                       // x.id=DemoClass2,y.id=DemoClass1

因此修改了构造器的prototype字典,所有由该构造器生成的对象的属性就会发生改变,如果只是对一个对象实例修改了属性,其他对象实例不会受到影响,如

   1:  function DemoClass(){}
   2:  DemoClass.prototype.Name = "DemoClass";
   3:  DemoClass.prototype.IsNum = function(){return ture;};
   4:  var x = new DemoClass();
   5:  var y = new DemoClass();
   6:  DemoClass.prototype.Name = "DemoClass1"; /* x.Name == y.Name */
   7:  x.Name = "DemoClass2"; /* x.Name != y.Name */

注: 通过var DemoClass = {};或var DemoClass = { x: 10 };方式创建的对象不能使用构造函数new DemoClass(); 错误信息:DemoClass is not a constructor), 也不能使用prototype(错误信息:DemoClass.prototype is undefined

 

四、对象属性的读取和修改

由于每个对象实际上都会有两个字典,因此必然要有先后顺序,而且读取和修改的策略也不同

读取时,首先从对象自身的字典中读取,若找到则返回,未找到时再从__proto__指向的字典中查找,若找到则返回,若未找到则返回undefined。

修改时,直接向对象自身的字典中添加或修改,不对__proto__指向的字典操作

这样的策略保证了对单个对象属性的修改不会影响到其他对象,同样的对象在不同的运行时环境里就有了不同的行为即“动态性”。

五、再看构造器

看如下代码

   1:  function DemoClass(){}
   2:  DemoClass.prototype.Name = "DemoClass";
   3:  function DemoClass1(){}
   4:  DemoClass1.prototype.Name = "DemoClass1";
   5:  var x = new DemoClass();
   6:  var y = new DemoClass1();

声明两个构造器并且给每个构造器都实例化了对象,通过测试发现,两个构造器的prototype所指的字典并不相同,但是类型都为object

从这些可以看出,构造器被调用时,其prototype属性是一个object的实例,下面是用C来描述构造器和对象的结构

   1:   //构造器
   2:  struct Constructure{
   3:      object prototype;
   4:      Constructure(){
   5:           this.prototype = new object();
   6:           this.prototype.constructor = this;
   7:      }
   8:  }
   9:  //对象
  10:  struct Instance{
  11:       Constructure* __proto__;
  12:       object innerdict;//内部的字典
  13:       Instance(){
  14:           this.innerdict = new object();
  15:           this.__proto__ = JSRuntime["Constructure"];//通过运行时获取构造器地址
  16:       }
  17:  }

六、Javascript的变量

实际上Javascript中,变量 = 对象属性,这是因为 Javascript 在执行脚本之前会创建一个Global对象,所有的全局变量都是这个

Global对象的属性,执行函数时也会创建一个Activation对象,所有的局部变量都是这个Activation对象的属性。如下例:

var global = 42;

alert(this.global);    // 42, 可以通过this来访问Global对象

this.global2 = 12;

alert(global2);        // 12

 

function foo() {

    var local = 36;   // 不过无法直接访问Activation,因此无法通过 foo.local 的方式来访问local变量

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值