深入 JavaScript(4) - new运算符是如何工作的

接着上篇(//www.cnblogs.com/patrick-holynova/archive/2013/05/14/3077295.html), 来谈谈在OOP中重要的new运算.

JavaScript 不像高级语言C++, Java等本身就提供了对类的支持, 那么在Js中如何实现类, 类的实例?

  1. 对象字面量
  2. 用构造器创建

对象字面量, 例:

Detail = {
    'game': 'World of Warcraft',
    'class':  'Priest',
    'spell':   'Holy Nova'
}

 这种方式没什么好说的, 重点谈谈通过构造器创建实例.

什么是构造器? 前几篇已经说过很多遍了, 我们还可以叫它构造函数(下文开始都叫它构造函数了, 因为: ). 那么它自然是一个函数. 并且这个构造函数还带有一个名字是

prototype的属性, 这个属性指向的对象, 用于初始化实例的__proto__, 也就是说新的实例们继承了这个对象!

当然, 一个构造器还必须很多内部方法, 比如[[Construct]], 暂且不谈

构造函数须要通过 new 表达式来创建新对象. 如果不使用new, 则结果依赖于具体的构造函数的写法.

比如:

d1  = Date();    // "Mon May 20 2013 10:10:38 GMT+0800 (China Standard Time)"
// typeof d1 == 'string' , 产生了一个字符串, 不是一个'对象'.

d2 = new Date();    // typeof d2 == 'object' , d2为一个对象

 每个由构造函数创建的对象, 都有一个隐式引用到构造函数的原型对象.

d2.__proto__ === Date.prototype;    // true
Object.getPrototypeOf(d) === Date.prototype;    // true

 ------------

new 运算是如何工作的呢?

我们先假设有这样一个构造函数:

var WOWCharacter = function(cName) {
    var level = 0;
    
    this.name = cName;

    this.getLevel = function() { return this. level; }
    this.setLevel = function(lv) { this.level = lv; return this.getLevel(); }  
}

 现在创建一个角色, 创建一个类的实例:

var subsidiaryCharacter = new WOWCharacter('巫喵王');
// 现在subsidiaryCharater对象是这样的
{
    name: '巫喵王',
    getLevel: function(){...},
    setLevel: function(){...}
}

 你可能会问, level 属性哪儿去了? 其实它是一个'私有变量', 是不能直接访问的, 这个我最在文章最后介绍一点, 不是本篇重点.

new 的执行过程

  1. 创建一个新的对象, obj = new Object();
  2. 调用 WOWCharacter 构造函数: 传入参数(如果有的话), 本例中为 ('巫喵王'), 并且令构造函数中的 this 为 创建的新对象 obj
  3. 如果构造函数返回了一个对象, 那么最终的新实例为这个对象(本例中, 构造函数无返回值, 通常也是这么做的, 不让其有返回值.)
    如果构造函数没有返回一个对象, 那么就让第1步中创建的对象 obj 为最终的返回值. subsidiaryCharacter = obj.

-- over --

new运算聊完了, 上面提到私有变量的问题, level 就是一个私有的变量, 只能通过'特权函数' getLevel, setLevel访问.

直接 subsidiaryCharacter.level 是取不到值的, 为什么? 闭包

下次谈谈Js中的闭包吧.

posted @ 2013-05-20 11:39  zhongsp  阅读(1809)  评论(7编辑  收藏  举报