js基础知识温习:Javascript中如何模拟私有方法

本文涉及的主题虽然很基础,在很多人眼里属于小伎俩,但在JavaScript基础知识中属于一个综合性的话题。这里会涉及到对象属性的封装、原型、构造函数、闭包以及立即执行表达式等知识。

公有方法

公有方法就是能被外部访问并调用的方法。

// 在对象中
var Restaurant = {
  name: 'McDonald',
  // 公有方法
  getName: function() {
    return this.name;
  }
}

// 在构造函数中
function Person(name, age) {
  this.name = name;
  this.age = age;
  // 公有方法
  this.getName = function() {
    return this.name;
  }
}

// 在原型中
Person.prototype.getAge = function() {
  return this.age;
}

私有方法和特权方法

这两个方法一般放在一起讨论,原因在于我们定义的特权方法是指有权访问内部私有属性和私有方法的公有方法,而私有方法是指外部不可见且不可访问的方法。

通常定义一个对象的方式有二种,一是使用Object实例化或者对象表达式,二是使用构造函数。同样在不同的方式下面定义私有方法和特权方法的形式也不相同。

在对象中

这里我们通过Object对象表达式来创建一个对象并添加一些属性和方法,然后直接采用静态的方式调用。对象的私有数据放置在一个匿名函数立即执行表达式(IIFE)中。这意味着这个函数只存在于被调用的瞬间,一旦执行后就立即被销毁了。

在对象中创建私有数据的方式在对象的模式(指创建对象的模式)中被称之为模块模式,它的基本格式如下:

var yourObject = (function() {

  // 私有属性和方法

  return {
    // 公有方法和属性
  }
}) ();

在模块模式中,返回的对象字面量中只包含可以公开的属性和方法。

var Restaurant = (function() {
  // 私有属性
  var _total = 10;

  // 私有方法
  var _buyFood = function() {
    _total--;
  };
  var _getTotal = function() {
    return _total;
  }

  return {
    name: 'McDonald',
    getTotal: _getTotal,
    buy: _buyFood
  }
}) ();

Restaurant.buy();
console.log(Restaurant.name); // 'McDonald'
console.log(Restaurant.getTotal()); // 9

注意我们使用了闭包的方式来间接使用内部私有变量,同时对餐厅(Restaurant)名(name)进行了初始化。

在构造函数中

在上面介绍的模块模式创建私有方法时,公有方法和特权方法并没有什么本质上的区别,原因在于这个概念是来自于使用构造函数创建私有数据的时候定义出来的。

在构造函数中定义私有属性和方法很方便,我们不需要使用闭包,可以在调用的时候初始化数据。

function Restaurant(name) {
  // 私有属性
  var _total = 10;

  // 公有属性
  this.name = name;

  // 私有方法
  function _buyFood() {
    _total--;
  }

  // 特权方法
  this.buy = function() {
    _buyFood();
  }

  this.getTotal = function() {
    return _total;
  }
}

// 公有方法, 注意这里不能访问私有成员_total
Restaurant.prototype.getName = function() {
  console.log(_total); // Uncaught ReferenceError: _total is not defined
  return this.name;
}

var McDonald = new Restaurant('McDonald');
console.log(McDonald.getName()); // 'McDonald'
McDonald.buy();
console.log(McDonald.getTotal()); // 9

合二为一,更加灵活的方式

使用模块模式我们可以多次调用,每次执行完后都会被销毁掉。使用构造函数方式可以传入一些初始化的数据,但在公有方法中无法访问到私有成员属性,如果有很多公有方法需要访问私有数据,我们全部用特权方法来写,最后会给每个实例带去很多没有必要的方法。因此,将两者结合在一起可以长短互补,结合方式也很简单

var Restaurant = (function() {
  // 私有属性
  var _total = 10;

  // 私有方法
  function _buyFood() {
    _total--;
  }

  // 构造函数
  function restaurant(name) {
    this.name = name;
    this.getTotal = function() {
      return _total;
    }
  }

  restaurant.prototype.buy = function() {
    console.log(_total); // 10
    _buyFood();
  }

  restaurant.prototype.getName = function() {
    return this.name;
  }

  return restaurant;
}) ();

var McDonald = new Restaurant('McDonald');
console.log(McDonald.getName()); // 'McDonald'
McDonald.buy();
console.log(McDonald.getTotal()); // 9

总结

这个主题说实话,知识点远远不止这一点,但作者本人项目经验太少,文字功底太弱,很多东西不知道怎么描述。凑合着看一下,希望对新手有些帮助。

参考

-《JavaScript高级程序设计》(第3版)
-《JavaScript面向对象精要》
-《Effective JavaScript》

原文地址:https://www.cnblogs.com/wujie520303/p/4941228.html