想品客老师的第天:类
类是一个优化js面向对象的工具
类的声明
//1、
class User{}
console.log(typeof User)//function
//2、
let Hd=class{}
//其实跟1差不多
class Stu{
show(){}//注意这里不用加逗号,对象才加逗号
get(){
console.log('后盾人')
}
}
let hd=new Stu()
hd.get()//后盾人
类的原理
类的本质就是个函数,也就相当于【根据这个函数的原型的constructor】
class User{}
console.log(User===User.prototype.constructor)//true
类其实就是个语法糖的结构,意思是确实好用但是你又得背了。。。
类里面直接的、不加任何修饰的内容,都是默认写在原型里的:
class User{show(){console.log('我是个公共属性')
}}
console.dir(User);
类里面有个constructor函数,这个方法的功能是初始化内部的属性,和function里的this.属性名是一个作用:
class User {
constructor(name) {
this.name = name//和下面是一个作用
}
}
// console.log(User === User.prototype.constructor)//true
console.dir(User);
function Hd(name) {
this.name = name//和上面是一个作用
}
console.dir(Hd)
对象属性的声明
可以使用简单的this指针改变属性值为传入的形参,也可以用下面这种方法,更灵活:
class User {
site = "后盾人";
constructor(name) {
this.name = name;
}
changeSite(value) {
this.site = value;
}
show() {
return `${this.site}:${this.name}`;
}
}
let hd = new User("后盾人");
hd.changeSite("houdunren")//通过内部的方法声明hd对象内部的属性
console.log(hd.show());
类的遍历
上一篇我们提到了有些方法存在原型中,我们不需要遍历,只能用if (h.hasOwnProperty(key))来解决
而类就可以轻松做到这个,因为class声明的方法不能遍历
class Hd {
constructor(name) {
this.name = name
}
show() {
console.log('我在原型里')
}
}
let h = new Hd()
for (const key in h) {
console.log(key)//只打印name,不打印show方法
}
class默认在严格模式下的运行
这是一般函数在严格模式下的执行:
class Hd {
show() {
function test() {
console.log(this); // 严格模式下,this 是 undefined
}
test(); // 直接调用,没有绑定 this
}
}
let hd = new Hd();
hd.show(); // 在严格模式下,test() 中的 this 是 undefined
而类里面直接就按严格模式执行
class Hd {
show() {
function test() {
console.log(this);
}
test();
}
}
let hd = new Hd();
hd.show();
静态属性的使用
静态成员是就是构造函数或类里的属性和方法,静态属性就是构造函数或类里面的属性
在构造函数里定义静态属性:
function Web(url) {
this.url = url;
}
Web.url = "hdcms.com";
let hd = new Web("houdunren.com");
console.log(hd);
console.dir(Web);
在类里面设置静态属性
class Request {
static host = "https://www.houdunren.com";
api(url) {
return Request.host + `/${url}`;
}
}
let obj = new Request();
console.log(obj.api("article"));
像这种不改变的静态地址,最好前面加上static
静态方法的实现原理
在类中使用访问器
前面学过访问器,这是访问器在类的使用:
class Request {
constructor(host) {
this.data = {}
this.host = host
}
set host(url) {
if (!/^https:?\/\//i.test(url)) {
throw new Error('地址错误')
}
this.data.host = url
}
get host() {
return this.data['host']
}
}
let hd = new Request('https://houdunren.com')
属性保护
用命名原则保护属性
意思就是约定俗成的【下划线开头的】属性就是私有属性
class User {
_url = "https://houdunren.com";//被保护的,外部访问不了
constructor(name) {
this.name = name;
}
set url(url) {//但是url可以访问
if (!/^https?:/i.test(url)) {
throw new Error("非常网址");
}
this._url = url;
}
}
let hd = new User("后盾人");
hd.name = "李四";
hd.url = "https://hdcms.com";//所以通过url改变_url
console.log(hd);
使用Symbol定义protected属性
关于symbol可以保护数据这里之前在对象学过类似的概念,但是我没懂:
如果想保存的话可以把属性定为私有属性,symbol可以让他变成私有属性
"use strict"; const DATA = Symbol(); const user = { // name: "后盾人", [DATA]: { name }, age: 10, set name(value) { this[DATA].name = value; }, get name() { return this[DATA].name; } }; user.name = "hdcms"; // user.data.name = "你好"; console.log(user[Symbol()])
那你就要问了:symbol和私有属性什么关系,为啥symbol可以防止被修改?
deepseek太卡了,我们有请老朋友chatgpt作答:
Symbol 本身并没有提供不可修改(immutable)功能。它只是保证了每个 Symbol 是唯一的,也就是说它保证了属性键的唯一性,而不是数据本身的不可修改性。
但是,使用 Symbol 作为属性键可以间接达到“数据隐私”和“不可直接访问”的目的,因为 Symbol 属性不容易被外部直接修改。
怎么间接达到的?因为我们无法通过常规的方式来访问symbol定义的属性名的属性了:const DATA = Symbol("privateData"); // 创建一个唯一的 Symbol const user = { [DATA]: { name: "Alice", age: 25 }, // 用 Symbol 创建私有数据 get name() { return this[DATA].name; }, set name(value) { this[DATA].name = value; } }; console.log(user.name); // "Alice" user.name = "Bob"; // 调用 setter console.log(user.name); // "Bob" // 但是我们不能直接访问或修改 [DATA] 属性 console.log(user[DATA]); // undefined
在这个例子中,[DATA] 是一个私有的 Symbol 属性。虽然你可以通过 name 的 getter 和 setter 修改 name,但是无法直接通过 user[DATA] 来访问或修改 name。这是因为 Symbol 提供了 唯一性,使得你无法直接通过常规方式访问这个属性。
这样就只能用访问器修改数据了?了吗??
"use strict"; const DATA = Symbol(); const user = { // name: "后盾人", [DATA]: { name }, age: 10, set name(value) { this[DATA].name = value; }, get name() { return this[DATA].name; } }; //user.name = "hdcms"; user[DATA].name='荷叶饭' console.log(user[DATA])
可是我这么写的时候修改成功了啊?后盾人你在说什么?
const protecteds = Symbol();
class Common {
constructor() {
this[protecteds] = {};
this[protecteds].host = "https://houdunren.com";
}
set host(url) {
if (!/^https?:/i.test(url)) {
throw new Error("非常网址");
}
this[protecteds].host = url;
}
get host() {
return this[protecteds].host;
}
}
class User extends Common {
constructor(name) {
super();
this[protecteds].name = name;
}
get name() {
return this[protecteds].name;
}
}
let hd = new User("后盾人");
hd.host = "https://www.hdcms.com";
console.log(hd.name);