javascript中模拟类的私有,共有,静态属性

本文探讨了JavaScript中如何合理地使用原型对象来定义类的方法,并解释了为何不应使用原型来创建对象属性。同时介绍了如何模拟私有静态属性和方法。
javascript中,每个function都拥有一个原型对象prototype,通过这个对象可以为这个类定义各种属性和方法,但是这样定义的属性和方法是所有该类的对象所共有的,效果上和同这个类的父类中继承的字段和方法差不多。通常我们使用function的原型来创建类的方法,而用普通方式来创建类的属性。
1.为什么不用原型来创建属性
因为原型创建的内容是这个类所有对象所共享的,对于一个属性而言,不同的类的对象的值都不一样。如果使用原型对象来创建对象属性,那么任何一个类的对象修改了自己的某个属性,其他对象的相同属性也会被修改。
这么做的本质是因为:属性是各个对象不同的,要求对象自己保存自己该属性的值,而方法对于所有对象而言都是一样的,没有必要每个对象都保存一个方法,只要由类的原型保存一份,各个对象使用方法的时候调用这些方法就可以了。

2.为什么要用原型来保存方法
因为方法对所有类对象来说都是一样的,如果用传统方式定义,那样每个类的对象被定义的时候,该对象都会保存这个方法的信息,这样会耗
费很多资源。而使用原型来保存,所有的方法都保存在原型中,每个对象需要使用方法的时候就调用原型对象中保存的方法。节省了资源。


在类中定义共享的共有方法,私有静态属性和方法,共有静态属性和方法。
//一种更为合适的公用属性和方法的定义,把共有方法在类第一次调用的时候加到类的原型对象中
var Book = function(name){
//公有属性,在构造方法里面来定义,通过this关键字
this.name = name;
//第一次执行该对象的构造方法,这个时候执行下面的代码
//为类的原型对象上定义共有的方法
//所有该类的对象共享相同的共有对象,减小了内存的消耗
if (typeof Book._init == "undefined") {//在第一次定义该类对象的时候会成立
//共有的方法,在原型对象上定义
Book.prototype.setName = function(nname) {
this.name = nname;
};
Book.prototype.getName = function(){
return this.name;
};
Book.prototype.getCount = function(){
addCount();
return count;
};
}
//类已经被定义过了,以后就不再重新定义原型对象上的方法了
Book._init = true;
//利用局部变量来模拟私有静态属性和方法
//这些局部变量定义出来的方法和属性外界不能直接访问,只能通过公有方法访问,
var count = 0;
var addCount = function(){
count++;
}
};
//定义共有静态属性
Book.staticValue = 10;
//定义共有的静态方法
Book.changeValue = function() {
Book.staticValue++;
}
对上面类的调用方法
//这个new操作相当于先创建了一个简单对象,调用了类的构造方法
var book1 = new Book("AJAX");
var book2 = new Book("AJAX1");
alert(book1.getName());
alert(book2.getName());
book1.setName("JAVA");
alert(book1.getName());
alert(book2.getName());
alert(book1.getCount());
alert(book2.getCount());
alert(book1.getCount());
//共有的静态属性和方法要用类名来调用
alert(Book.staticValue);
Book.changeValue();
alert(Book.staticValue);


定义一个对象,希望这个对象拥有一些自己独享的私有信息
方法:直接定义一个匿名的类
//一个单独的对象,期望拥有一些私有有的信息

下面的方法和上面的起到一样的效果,
//利用匿名方法直接调用的方式,来实现一个对象拥有私有的信息
var priObj = (function(name){
//由于这个变量是在方法内定义的,起到的效果就是私有的
var priname = name;
//这个格式要求返回的是一个对象,
//这个对象要求有getName和setName两个方法
return {
getName:function() {
return priname;
},
setName:function(nname) {
priname = nname;
}
};
})("wang");

下面是上面对象的使用方法
//var priObj1=new priObj("a");
//var priObj2=new priObj("b");
上面的做法是错误的,因为这个priObj已经是个定义好的对象了,在定义匿名类的同时就定义好的,所以不能再这么去new了。
//priObj.priname是私有内容,无法访问
alert(priObj.priname);
alert(priObj.getName());
priObj.setName("Lee");
alert(priObj.getName());
alert("");
<think>我们正在讨论JavaScript中的(class)的静态变量(static variable)和私有变量(private variable)的区别及用法。 根据用户的问题,我们需要明确以下几点: 1. 静态变量(static variable)是级别的,属于本身,而不是的实例。它们通过`static`关键字定义。 2. 私有变量(private variable)是实例级别的,并且只能在内部访问。它们通过`#`前缀(ES2022正式支持)或通过闭包(传统方式)实现。 我们将分别介绍静态变量和私有变量的定义、用法和区别,并给出代码示例。 注意:在JavaScript中,私有变量(使用#)是真正私有的,不能在外部访问。而静态变量(使用static)是本身的属性。 下面我们详细说明: ### 静态变量(Static Variables) - 静态变量属于本身,而不是的任何实例。 - 使用`static`关键字在内部声明。 - 可以通过名直接访问,也可以通过静态方法访问,但不能通过的实例访问(除非通过名)。 - 通常用于存储与相关的常量或与所有实例共享的数据。 ### 私有变量(Private Variables) - 私有变量属于的每个实例,但只能在内部访问。 - 使用`#`前缀声明(ES2022及以后),或者通过WeakMap和闭包模拟(旧方法)。 - 不能在外部直接访问,包括实例也不能直接访问(除非通过内部的方法)。 - 通常用于封装实例的内部状态,避免外部直接修改。 代码示例: ```javascript class MyClass { // 静态变量 static staticVariable = "I am static"; // 私有变量(使用#) #privateVariable; constructor(value) { this.#privateVariable = value; } // 静态方法 static staticMethod() { return `Static method: ${this.staticVariable}`; // 注意:在静态方法中,this指向本身(MyClass) } // 实例方法,可以访问私有变量 getPrivate() { return this.#privateVariable; } } // 访问静态变量 console.log(MyClass.staticVariable); // "I am static" console.log(MyClass.staticMethod()); // "Static method: I am static" // 创建实例 let obj = new MyClass("Hello"); console.log(obj.getPrivate()); // "Hello" // 以下访问都会导致错误 // console.log(obj.#privateVariable); // SyntaxError: Private field '#privateVariable' must be declared in an enclosing class // console.log(obj.staticVariable); // undefined (因为静态变量不属于实例) ``` 在上面的例子中: - `staticVariable`是静态变量,通过`MyClass.staticVariable`访问。 - `#privateVariable`是私有变量,只能在内部通过`this.#privateVariable`访问,外部无法直接访问。 另外,我们也可以使用静态私有变量(即静态私有的变量),这可以通过在静态变量前加`#`来实现(但注意,静态私有变量也是ES2022的特性): ```javascript class MyClass { static #privateStaticVariable = "I am private static"; static getPrivateStatic() { return this.#privateStaticVariable; } } console.log(MyClass.getPrivateStatic()); // "I am private static" // console.log(MyClass.#privateStaticVariable); // 错误,无法在外部访问 ``` ### 区别总结 | 特性 | 静态变量 | 私有变量 | |--------------|----------------------------------|----------------------------------| | 所属 | 本身 | 的实例 | | 访问方式 | 通过名访问(`ClassName.var`) | 只能在内部访问(使用`#`前缀) | | 存储位置 | (构造函数)上 | 每个实例内部 | | 共享性 | 所有实例共享 | 每个实例独立 | | 如何声明 | `static`关键字 | `#`前缀 | 希望这个解释和示例能帮助你理解。 如果用户有进一步的问题,我们可以生成相关问题。 §§相关问题§§ 1. 在JavaScript中,静态私有变量是如何声明的? 2. 除了使用`#`,还有哪些方法可以实现私有变量? 3. 静态方法中能否访问私有变量?为什么? 4. 私有变量和静态变量在继承中表现如何?</think>### JavaScript 静态变量与私有变量的区别及用法 #### **1. 静态变量 (Static Variable)** - **定义**:使用 `static` 关键字声明,属于本身而非实例。 - **特性**: - 通过名直接访问:`ClassName.staticVar` - 所有实例共享同一内存地址 - 常用于工具方法或全局配置 - **示例**: ```javascript class Config { static API_KEY = "abc123"; // 静态变量 static getBaseUrl() { // 静态方法 return "https://api.example.com"; } } console.log(Config.API_KEY); // "abc123"(直接通过访问) ``` #### **2. 私有变量 (Private Variable)** - **定义**:使用 `#` 前缀声明,仅在内部可访问。 - **特性**: - 每个实例拥有独立副本 - 外部直接访问会报错:`SyntaxError` - 需通过公共方法(如 getter/setter)间接操作 - **示例**: ```javascript class User { #id; // 私有变量 constructor(id) { this.#id = id; } // 公共方法访问私有变量 getUserId() { return this.#id; } } const user = new User(100); console.log(user.getUserId()); // 100 // console.log(user.#id); // 报错:Private field '#id' must be declared in an enclosing class ``` --- #### **核心区别对比** | **特性** | **静态变量** | **私有变量** | |------------------|----------------------------------|----------------------------------| | **作用域** | 级别 | 实例级别 | | **访问方式** | `ClassName.staticVar` | 仅限内部通过 `#var` 访问 | | **内存分配** | 所有实例共享同一内存 | 每个实例独立存储 | | **用途** | 全局配置/工具函数 | 封装敏感数据(如ID、密码) | | **语法** | `static var = value` | `#var = value` | --- #### **混合使用场景** ```javascript class Logger { static #logLevel = "DEBUG"; // 静态私有变量(级别私有) static setLogLevel(level) { this.#logLevel = level; } static log(message) { console.log(`[${this.#logLevel}] ${message}`); } } Logger.setLogLevel("ERROR"); Logger.log("System crashed"); // [ERROR] System crashed // Logger.#logLevel; // 报错(外部不可访问) ``` --- #### **注意事项** 1. **浏览器兼容性**: - 私有变量 (`#`) 需 ES2022+ 或 Babel 转译 - 旧版 JS 可通过闭包模拟私有性(非真正私有): ```javascript function OldClass() { const privateVar = "secret"; // 闭包私有变量 this.getPrivate = () => privateVar; } ``` 2. **设计原则**: - 静态变量:减少全局污染,替代全局变量[^1] - 私有变量:强化封装性,避免外部意外修改[^2] 3. **静态私有变量**: - 声明:`static #var` - 作用:级别私有数据(如内部配置) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值