JavaScript 对象封装:公有、私有与特权方法的实现与对比

作者:半夏时间:2026-10-29 16:30:26浏览:484

本文深入解析 JavaScript 中对象属性的封装机制,详细对比公有方法、私有方法与特权方法的定义与实现。通过模块模式(IIFE)和构造函数两种路径,阐述如何利用闭包保护内部状态,并探讨将两者结合以优化实例内存占用的最佳实践。

JavaScript 对象封装概述

本文探讨的主题虽属基础,常被视作技巧,但在 JavaScript 知识体系中具有综合性。内容涵盖对象属性封装、原型链、构造函数、闭包以及立即执行函数表达式(IIFE)等核心概念。

公有方法的定义

公有方法即允许外部直接访问和调用的方法。


// 在对象中
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

以上内容总结了部分核心知识点,更多细节建议读者自行探索研究,希望本文对初学者有所助益。

作者最新文章