JavaScript 对象封装:公有、私有与特权方法的实现与对比
本文深入解析 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
以上内容总结了部分核心知识点,更多细节建议读者自行探索研究,希望本文对初学者有所助益。
JavaScript闭包与类(Class)的区别及适用场景对比
2026-11-05 15:48:57
JavaScript入门要学ES6吗?let与箭头函数等新特性解析
2026-11-05 14:49:16
JavaScript 8种数据类型详解:基本类型与引用类型的区别
2026-11-05 14:25:15
怎么在JavaScript中使用async/await优化Ajax异步流程
2026-11-05 13:56:15
JavaScript replace回调函数实现动态正则替换逻辑
2026-11-05 13:52:13
