javascript 面向对象精要 第六章 对象模式

6.1 私有成员和特权成员

JavaScipt 对象的所有属性都是公有的,没有显式的方法指定某个属性不能被外界访问。

在不希望公有的属性名字前面加上下划线。

6.1.1 模块模式

模块模式是一种用于创建拥有私有数据的单件对象的模式。

基本做法是使用立即调用函数表达式(IIFE)来返回一个对象。该函数表达可以包括任意数量的本地变量,在函数外不可见。模块模式的基本格式如下:

var yourObj = (function(){
    // private data variables

    return {
        // public methods and properties
    }
}());

该模式创建了一个匿名函数,并立即执行。尾部额外的小括号,可以用这种语法立刻执行匿名函数,意味着这个函数仅存在于被调用的瞬间。

模块模式还有一个变种叫暴露模块模式,他将所有的变量和方法都组织在IIFE的顶部,然后将他们设置到需要被返回的对象上。

//  一般写法
var yourObj = (function(){
    var age = 25;

    return {
        name: "hui",
       getAge: function(){
            return age;
        },
       growOlder:function(){
         age++;
      };
}());
// 暴露模块模式
var yourObj = (function(){
    var age = 25;
    function getAge(){
        return age;
    }
    
 growOlder:function(){
         age++;
      };
return {
 name: "hui",
 getAge: getAge,   
 growOlder: growOlder; }
}());

6.1.2 构造函数的私有成员(不能通过对象直接访问)

模块模式在定义单个对象的私有属性十分有效,但对于那些同样需要私有属性的自定义类型呢?你可以在构造函数中使用类似的模式来创建每个实例的私有数据。

6.2 混入

javascript中大量使用了伪类继承和原型对象继承,还有一种伪继承的手段叫混入。一个对象在不改变原型对象链的情况下得到了另外一个对象的属性被称为“混入”。因此,和继承不同,混入让你在创建对象后无法检查属性来源。
纯函数实现:

function mixin(receiver, supplier){
    for(var property in supplier){
        if(supplier.hasOwnProperty(property)){
            receiver[property] = supplier[property];
        }
    }
}

函数mixin()接受两个参数,接收者和提供者。函数作用为将提供者所有的可枚举属性复制给接收者。可以通过for in循环迭代提供者的属性并将值设置给接收者的同名属性达成这一目的。

这是浅拷贝,如果属性的值是一个引用,那么两者将指向同一个对象。

6.3 作用域安全的构造函数

如下例

function Person(name){
  this.name=name;
}
Person.prototype.sayName=function(){
 console.log(this.name);
};
var person1=Person("hui");    //missing "new"
  console.log(person1 instanceof Person);
    console.log(typeof person1);
    console.log(name);

运行结果如下:


Person构造函数不是用new操作符调用的,我们创建了一个全局变量name,这段代码运行于非严格模式,如果在严格模式下这么做会抛出一个错误。

很多内建构造函数;例如Array、RegExp不需要new也可以工作,这是因为他们被设计为作用域安全的构造函数。

一个作用域安全的构造函数有没有new都可以工作,并返回同样类型的对象。

当用new调用一个函数,this指向的新创建的对象已经属于该构造函数所代表的自定义类型。(在函数内用instanceof来检查自己是否被new调用)

一个作用域安全的Person的版本如下

function Person(name){
     if (this instanceof Person){
          this.name=name;
       }else{
          return new Person(name);
      }    
}

对于上述构造函数,当自己被new调用时设置name属性。否则,则用new递归调用来为对象创建正确的实例。

javascript 本身也提供了很多作用域安全的构造函数,例如Object() Array() RegExp() Error().

猜你喜欢

转载自blog.csdn.net/runner_123/article/details/79791460