Javascript——Symbol简单了解

一、Symbol(符号)

1.1 MDN链接:yield - JavaScript | MDN (mozilla.org)

1.2 Symbol简介

Symbol(符号)是ECMAScript6新增的数据类型。符号是原始值,且符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。尽管符号听起来跟私有属性有点类似,但符号并不是为了提供私有属性的行为才增加的(尤其是因为Object API提供了方法,可以更方便地发现符号属性)。相反,符号就是用来创建唯一记号,进而用作非字符串形式的对象属性。

① Symbol没有字面量语法,你只要创建Symbol()实例并将其用作对象的新属性,就可以保证它不会覆盖已有的对象属性,无论是符号属性还是字符串属性。

let genericSymbol = Symbol();
console.log(genericSymbol) // Symbol();let fooSymbol = Symbol('foo');
console.log(fooSymbol); // Symbol(foo);

② Symbol()函数不能用作构造函数,与new关键字一起使用。这样做是为了避免创建符号包装对象,像使用Boolean、String或Number那样,它们都支持构造函数且可用于初始化包含原始值的包装对象。

let mySymbol = new Symbol(); // TypError: Symbol is not a constructor// 如果确实想使用符号包装对象,可以借用Object()函数
let mySymbol2 = Symbol();
let myWrappedSymbol = Object(mySymbol2);
console.log(typeof myWrappedSymbol); // object

二、符号中的一些方法

2.1 使用全局符号注册表:Symbol.for()

Symbol.for()方法:运行时不同部分需要共享和重用符号实例,可以通过Symbol.for注册在全局注册表。

提示:全局注册表中的符号必须使用字符串来创建,传给Symbol.for的参数会自动转为字符串。

// 验证通过Symbol.for注册在全局注册表的符号是共享的let fooGlobalSymbol = Symbol.for("foo");
let otherFooGlobalSymbol = Symbol.for("foo");console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true

2.2 查询全局注册表:Symbol.keyFor()

// 创建全局符号
let s = Symbol.for('foo');
console.log(Symbol.keyFor(s)); //foo// 创建普通符号
let s2 = Symbol('bar');
console.log(Symbol.keyFor(s2)); // undefined// 如果传给Symbol.keyFor()的不是符号,则该方法抛出TypeError
Symbol.keyFor(123); // TypeError: 123 is not a Symbol

2.3 使用符号作为属性

凡是可以使用字符串或数值作为属性的地方,都可以使用符号。这就包括了对象字面量属性和Object.defineProperty()/Object.definedProperties()定义的属性。对象字面量只能在计算属性语法中使用符号作为属性。

let s1 = Symbol('foo'),s2 = Symbol('bar'),s3 = Symbol('baz'),s4 = Symbol('qux');let o = {[s1]: 'foo val'
};
// 这样也可以:o[s1] = 'foo val';
console.log(o);
// { Symbol(foo): foo val }Object.defineProperty(o, s2, { value: 'bar val' });console.log(o);
// {Symbol(foo): foo val, Symbol(bar): bar val}Object.defineProperties(o, {[s3]: {value: 'baz val'},[s4]: {value: 'qux val'}
});console.log(o);
// {Symbol(foo): foo val, Symbol(bar): bar val,
// Symbol(baz): baz val, Symbol(qux): qux val }

2.4 获取对象中的普通/符号属性数组

(1)Object.getOwnPropertyNames:返回对象实例的常规属性数组;
(2)Object.getOwnPropertySymbols:返回对象实例的符号属性数组

(3) Object.getOwnPropertyDescriptors:返回常规和符号属性描述符对象

(4)Reflect.ownKeys:同时返回常规和符号属性键数组

let s1 = Symbol('foo'),s2 = Symbol('bar');let o = {[s1]: 'foo val',[s2]: 'bar val',baz: 'baz val',qux: 'qux val'
};
// ["baz","qux"]
console.log(Object.getOwnPropertyNames(o));// [Symbol(foo),Symbol(bar)]
console.log(Object.getOwnPropertySymbols(o));// {baz: {...}, qux: {...}, Symbol(foo): {...}, Symbol(bar): {...}}
console.log(Object.getOwnPropertyDescriptors(o));// ["baz", "qux", Symbol(foo), Symbol(bar)]
console.log(Reflect.ownKeys(o));

提示:因为符号属性是对内存中符号的一个引用,所以直接创建并用作属性的符号不会丢失。但是,如果没有显示地保存对这些属性的引用,那么必须遍历对象的所有符号属性才能找到相应的属性键。

三、常用内置符号

ECMAScript6引入了一些常用内置符号,用于暴露语言内部行为,开发者可以直接访问、重写或模拟这些行为。

3.1 Symbol.asyncIterator

Symbol.asyncIterator是ES2018规范定义的,因此只有版本非常新的浏览器支持它!

Symbol.asyncIterator 符号指定了一个对象的默认异步迭代器。如果一个对象设置了这个属性,它就是异步可迭代对象,可用于for await ...of循环。

3.1.1 自定义异步可迭代对象。

我们可以通过设置[Symbol.asyncIterator]属性来自定义异步可迭代对象。

demo(这里直接用MDN上的一个demo):

const myAsyncIterator = new Object();myAsyncIterator[Symbol.asyncIterator] = async function* () {yield "hello";yield "async";yield "iteration!";yield () => {};
};(async () => {for await (const x of myAsyncIterator) {console.log("x=", x);}// "expected output://     "hello"//     "async"//     "iteration!"//     () => {}
})();

3.1.2 内建异步可迭代对象

目前没有默认设定了[Symbol.asyncIterator]属性的Javascript内建的对象。不过,WHATWG(网页超文本应用技术工作小组)Streams会被设定为第一批异步可迭代对象,[Symbol.asyncIterator]最近已在设计规范中落地。

3.2 Symbol.hasInstance

Symbol.hasInstance用于判断对象是否为构造器的实例。因此你可以用它自定义instanceof操作符在某个类上的行为。该方法决定一个构造器是否认可一个对象是它的实例。由instanceof操作符使用,instanceof操作符可以用来确定一个对象实例的原型链上是否有原型。

instanceof的典型使用场景如下:

function Foo() {};let f = new Foo();
console.log(f instanceof Foo); // trueclass Bar {}
let b = new Bar();
console.log(b instanceof Bar); // true

标注①:在ES6中,instanceof操作符会使用Symbol.hasInstance函数来确定关系。以Symbol.hasInstance为键的函数会执行同样的操作,只是操作数对调了一下:

function Foo() {}
let f = new Foo();
console.log(Foo[Symbol.hasInstance](f)); // trueclass Bar {}
let b = new Bar();
console.log(Bar[Symbol.hasInstance](b)); // true

这个属性定义在Function的原型上,因此默认在所有函数和类上都可以调用。由于instanceof操作符会在原型链上寻找这个属性定义,就跟在原型链上寻找其它属性一样,因此可以在继承的类上通过静态方法重新定义这个函数:

class Bar {}
class Baz extends Bar {static [Symbol.hasInstance]() {return false;}
}let b = new Baz();
console.log(Bar[Symbol.hasInstance](b)); // true
console.log(b instanceof Bar);
console.log(Baz[Symbol.hasInstance](b)); // false
console.log(b instanceof Baz); // false

结论:通过上面这个案例中的代码:“b instanceof Baz”,我们验证了标注①位置的结论:在ES6中的操作符 instanceof实际上会使用Symbol.hasIntance来确定关系(通过Symbol.hasInstance可以重写instanceof操作符的行为)。

3.3 Symbol.isConcatSpreadable

        根据ECMAScript规范,这个符号这个符号作为一个属性表示“一个布尔值,如果是true,则意味着对象应该用Array.prototype.concat()打平其数组元素”。ES6中的Array.prototype.concat()方法会根据接收到的对象类型选择如何将一个类数组对象拼接成数组实例。覆盖Symbol.isConcatSpreadable的值可以修改这个行为。

        数组对象默认情况下会被打平到已有的数组,false或假值会导致整个对象被追加到数组末尾。类数组对象默认情况下会被追加到数组末尾,true或真值会导致这个类数组对象被打平到数组实例。其它不是类数组对象的对象在Symbol.isConcatSpreadable被设置为true的情况下将被忽略

可以直接理解成,该属性用来配置连接A([1])和B数组[2]时,执行A.concat(B)是否会展开B数组连接,如果给A的Symbol.isConcatSpreadable赋值成false时,此时A.concat(B)的结果时:[1,[2]],如果不给A的Symbol.isConcatSpreadable赋值,此时打印Symbol.isConcatSpreadable的值是undefined,执行后的结果是:[1, 2]。

let initial = ['foo'];
let array = ['bar'];console.log(array[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(array)); // ['foo', 'bar']
array[Symbol.isConcatSpreadable] = false;
console.log(initial.concat(array)); // ['foo', ['bar']]let arrayLikeObject = {length: 1, 0: 'baz'}
console.log(arrayLikeObject[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(arrayLikeObject)); // ['foo', {...}]
arrayLikeObject[Symbol.isConcatSpreadable] = true;
console.log(initial.concat(arrayLikeObject)); // ['foo', 'baz']let otherObject = new Set().add('qux');
console.log(otherObject[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(otherObject));
otherObject[Symbol.isConcatSpreadable] = true;
console.log(initial.concat(otherObject)); // ['foo']

3.4 Symbol.iterator

根据ECMAScript规范,这个符号作为一个属性表示“一个方法,该方法返回对象默认的迭代器。由for-of使用”。换句话说,这个符号实现迭代器的API的函数。for-of循环这样的语言结构会利用这个函数执行迭代操作。循环时,它们会调用以Symbol.iterator为键的函数,并默认这个函数会返回一个实现迭代器API的对象。很多时候,返回的对象是实现该API的Generator:

class Foo {*[Symbol.iterator](){}
}
let f = new Foo();
consoe.log(f[Symbol.iterator]();

技术上,这个由Symbol.iterator函数生成的对象应该通过next()方法陆续返回值。可以通过显式地调用next()

class Emitter {constructor(max) {this.max = max;this.idx = 0;}*[Symbol.iterator] () {while(this.idx < this.max) {yield this.idx++;}}
}
function count() {let emitter = new Emitter(5);for(const x of emitter) {console.log(x);}
}
count();

3.5 Symbol.match

根据ECMAScript规范,这个符号作为一个属性表示“一个正则表达方法,该方法用正则表达式去匹配字符串。由String.prototype.match为键的函数来对正则表达式求值。正则表达式的原型上默认有这个函数的定义,因此所有的正则表达式实例默认是这个String方法的有效参数;

可以通过Symbol.match重写String.prototype.match

class FooMatcher {static [Symbol.match](target) {return target.includes('foo');}
}console.log('foobar'.match(FooMatcher)); // true
console.log('barbaz'.match(FooMatcher)); // false

给String.prototype.match这个方法传入非正则表达式值会导致该值被转换成RegExp对象。如果想要改变这种行为,让方法直接使用参数,则可以重新定义Symbol.match函数以取代默认对正则表达式求值的行为,从而让match()方法使用非正则表达式实例。Symbol.match函数接收一个参数,就是调用match()方法的字符串实例。返回的值没有限制:

class FooMatcher {static [Symbol.match](target) {return target.includes('foo');}
}console.log('foobar'.match(FooMatcher)); // true
console.log('barbaz'.match(FooMatcher)); // falseclass StringMatcher {constructor(str) {this.str = str;}[Symbol.match](target) {return target.includes(this.str);}
}
console.log('foorbar'.match(new StringMatcher('foo'))); // true
console.log('barbaz'.match(new StringMatcher('qux'))); // false

3.6 Symbol.replace

根据ECMAScript规范,这个符号作为一个属性表示“一个正则表达式方法,该方法替换一个字符串中匹配的子串。由String.prototype.replace()方法使用”。String.prototype.replace()方法会使用以Symbol.replace为键的函数来对正则表达式求值。正则表达式的原型上默认有这个函数的定义,因此所有正则表达式实例默认是这个String方法的有效参数。

可以通过Symbol.replace来重写String.prototype.replace方法

console.log(RegExp.prototype[Symbol.replace]);
// f [Symbol.replace]() { [native code] }console.log('foobarbaz'.replace(/bar/, 'qux');
// 'fooquxbaz'

给这个方法传入非正则表达式值会导致该值被转换为RegExp对象。如果想改变这种行为,让方法直接使用参数,可以重新定义Symbol.replace函数以取代默认对正则表达式求值的行为,从而让replace()方法使用非正则表达式实例。Symbol.replace函数接收两个参数,即调用replace()方法的字符串实例和替换字符串。返回的值没有限制

class FooReplacer {static [Symbol.replace](target,replacement) {return target.split('foo').join(replacement);}
}
console.log('barfoobaz'.replace(FooReplacer, 'qux'));
// "barquxbaz"class StringReplacer {constructor(str) {this.str = str;}[Symbol.replace](target, replacement) {return target.split(this.str).join(replacement)}
}
console.log('barfoobaz'.replace(new StringReplacer('foo'), 'qux'));

3.7 Symbol.search

根据ECMAScript规范,这个符号作为一个属性表示“一个正则表达式方法,该方法返回字符串中匹配正则表达式的索引。由String.prototype.search()方法使用”。String.prototype.search()方法会使用以Symbol.search为键的函数来对正则表达式求值。正则表达式 的原型上默认有这个函数的定义,因此所有正则表达式实例默认是这个String方法的有效参数:

可以通过Symbol.search来重写String.prototype.search这个方法

console.log(RegExp.prototype[Symbol.search]);
// f [Symbol.search]() { [native code] }console.log('foobarbaz'.search(/bar/));
// 3

给这个方法传入非正则表达式值会导致该值被转换为RegExp对象。如果想改变这种行为,让方法直接使用参数,可以重新定义Symbol.search函数以取代默认对正则表达式求值的行为,从而让search方法使用非正则表达式实例。Symbol.search函数接收一个参数,即调用search方法的字符串实例。返回的值没有限制

class FooSearcher {static [Symbol.search](target) {return target.indexOf('foo')}
}
console.log('foobar'.search(FooSearcher)); //0
console.log('barfoo'.search(FooSearcher)); // 3
console.log('barbaz'.search(FooSearcher)); // -1class StringSearcher {constructor(str) {this.str = str;}[Symbol.search](target) {return target.indexOf(this.str)}
}console.log('foobar'.search(new StringSearcher('foo'))); // 0
console.log('barfoo'.search(new StringSearcher('foo'))); // 3
console.log('barbaz'.search(new StringSearcher('foo'))); // -1

3.8 Symbol.species

根据ECMAScript规范,这个符号作为要给属性表示“一个函数值,该函数作为创建派生对象的构造函数”。这个属性在内置类型中最常用,用于对内置类型实例方法的返回值暴露实例化派生对象的方法。用Symbol.species定义静态的获取器(getter)方法,可以覆盖新创建实例的原型定义:

class Bar extends Array {}
class Baz extends Array {static get [Symbol.species]() {return Array}
}let bar = new Bar();
console.log(bar)
console.log(bar instanceof Array); // true
console.log(bar instanceof Bar); // true
bar = bar.concat('bar');
console.log(bar instanceof Array); // true
console.log(bar instanceof Bar); // truelet baz = new Baz();
console.log(baz instanceof Array); // true
console.log(baz instanceof Baz); // true
baz = baz.concat('baz');
console.log(baz instanceof Array); // true
console.log(baz instanceof Baz); // false

species本身的作用自行去了解一下

3.9 Symbol.split

根据ECMAScript规范,这个符号作为一个属性表示“一个真个则表达式方法,该方法再匹配正则表达式的索引位置拆分字符串。由String.prototype.split()方法使用”。String.prototype.split方法会使用以Symbol.split为键的函数来对正则表达式求值。正则表达式的原型上默认有这个函数定义,因此所有正则表达式实例默认是这个String方法的有效参数:

console.log(RegExp.prototype[Symbol.split]);
// f [Symbol.split]() { [native code] }
console.log('foobarbaz'.split(/bar/));
// ['foo', 'baz']

给这个方法传入非正则表达式值会导致该值被转换为RegExp对象。如果想改变这种行为,让方法直接使用参数,可以重新定义Symbol.split函数以取代默认对正则表达式求值的行为,从而让search方法使用非正则表达式实例。Symbol.split函数接收一个参数,即调用split方法的字符串实例。返回的值没有限制

class FooSplitter {static[Symbol.split](target) {return target.split('foo');}
}
console.log('barfoobaz'.split(FooSplitter));
// ["bar", "baz"]class StringSplitter {constructor(str) {this.str = str;}[Symbol.split](target) {return target.split(this.str);}
}
console.log('barfoobaz'.split(new StringSplitter('foo')));
// ["bar", "baz"]

3.10 Symbol.toPrimitive

3.11 Symbol.toStringTag

3.12 Symbol.unscopables

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/772079.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TCP(socket 套接字)编程 1

一、TCP套接字编程架构如下 二、相关代码实现 1、服务器端代码 package com.company;import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket;public class Main {public static void main(String[] args) {…

5.88 BCC工具之tcpsynbl.py解读

一,工具简介 tcpsynbl工具以直方图的形式显示SYN到达时的TCP SYN积压大小。这可以让我们了解应用程序距离达到积压限制并丢弃SYN(导致SYN重传产生性能问题)还有多远。 TCP SYN 数据包则通常用于启动 TCP 三次握手过程的第一次握手。 二,代码示例 #!/usr/bin/env python…

javaWeb健身房管理系统

一、简介 随着人们健康意识的增强和生活水平的提高&#xff0c;健身已经成为了现代人生活中不可或缺的一部分。为了更好地管理健身房的日常运营&#xff0c;我们设计并开发了一款基于 JavaWeb 的健身房管理系统。本系统采用了最新的技术&#xff0c;包括 Spring Boot、MyBatis…

nacos集群搭建实战

集群结构图 初始化数据库 Nacos默认数据存储在内嵌数据库Derby中&#xff0c;不属于生产可用的数据库。官方推荐的使用mysql数据库&#xff0c;推荐使用数据库集群或者高可用数据库。 首先新建一个数据库&#xff0c;命名为nacos&#xff0c;而后导入下面的SQL&#xff08;直…

智慧工地源码 数字孪生可视化大屏 工地管理平台系统源码 多端展示(PC端、手机端、平板端)

智慧工地源码 数字孪生可视化大屏 工地管理平台系统源码 多端展示&#xff08;PC端、手机端、平板端&#xff09; 智慧工地系统多端展示&#xff08;PC端、手机端、平板端&#xff09;;数字孪生可视化大屏&#xff0c;一张图掌握项目整体情况;使用轻量化模型&#xff0c;部署三…

ubuntu22.04配置Azure Kinect DK深度相机

一.安装SDK 今天我来配置一下微软公司的Azure Kinect DK深度相机,以前在ubuntu18.04上配置过,因为官方说唯一支持linux版本是18.04,所以在18.04中配置还算顺利 but这不代表不可以在更高版本的ubuntu中使用,只不过需要自己去多配置一些东西 apt 源安装 更新源: c…

25.7 MySQL 数据库和表的基本操作

1. 基础知识 1.1 一条数据的存储过程 存储数据确实是处理数据的基石, 只有确保数据被准确无误且有条理地存储, 我们才能对其进行深入的处理和细致的分析. 否则, 这些数据就像是一团毫无章法的乱麻, 让我们难以捉摸其内在的逻辑和价值.那么, 如何才能够将用户那些与经营紧密相关…

VITIS更新硬件平台

VITIS硬件平台更新以后如何重新导入 在之前建立的硬件平台上右击&#xff0c;选择Update Hardware Specification&#xff0c;选择最新导出的硬件平台文件&#xff1b; 重建板级支持包 选择复位重建BSP源文件&#xff0c;俩个地方的BSP都Reset一下&#xff0c;然后Build&…

使用SqlDataAdapter和DataSet维护数据库表数据

使用SqlDataAdapter和DataSet维护数据库表数据一般按照如下步骤操作&#xff1a; 1.建立数据库连接 2.使用sql查询语句创建SqlDataAdapter实例&#xff0c;并利用SqlCommandBuilder自动生成SqlDataAdapter对象的InsertCommand&#xff0c;UpdateCommand&#xff0c;DeleteCom…

Transformer的前世今生 day08(Positional Encoding)

前情提要 Attention的优点&#xff1a;解决了长序列依赖问题&#xff0c;可以并行。Attention的缺点&#xff1a;开销变大了&#xff0c;而且不存在位置关系为了解决Attention中不存在位置关系的缺点&#xff0c;我们通过位置编码的形式加上位置关系 Positional Encoding&…

LinkedIn账号为什么被封?被封后如何解决?

近期会有一些小伙伴说自己遇到了帐号无法登录的情况&#xff0c;其实出现领英帐号被封号(被限制登录)主要会有两类情况&#xff0c;今天就给大家分享一下如果被封该如何解决&#xff0c;强烈建议收藏。 在电脑领英官网或者手机领英APP上&#xff0c;输入领英帐号密码点击登录后…

Python语法中,对函数名字的定义应该遵循什么规则?

在Python语法中&#xff0c;函数名字的定义应遵循以下规则&#xff1a; 标识符命名规则&#xff1a;函数名是一个标识符&#xff0c;因此它必须遵循Python的标识符命名规则。函数名只能包含字母&#xff08;A-Z&#xff0c;a-z&#xff09;、数字&#xff08;0-9&#xff09;和…

NDI虚拟摄像头的使用

目录 一、软件 二、具体操作 1、启动ScreenCapture 2、启动Webcam 3、选择NDI“源”

系统学习Python——装饰器:“私有“和“公有“属性案例-[验证函数的参数:针对位置参数的一个基本范围测试装饰器]

分类目录&#xff1a;《系统学习Python》总目录 让我们从基本的范围测试实现开始。为了简化步骤&#xff0c;起初我们将编写一个只对位置参数有效的装饰器&#xff0c;并且假设这些参数在每次调用中总是出现在相同的位置。位置参数不能通过关键字名称传递&#xff0c;并且我们在…

HCIP的学习(4)

GRE和MGRE VPN---虚拟专用网络。指依靠ISP&#xff08;运营商&#xff09;或其他公有网络基础设施上构建的专用的安全数据通信网络。该网络是属于逻辑上的。​ 核心机制—隧道机制&#xff08;封装技术&#xff09; GRE—通用路由封装 ​ 三层隧道技术&#xff0c;并且是属于…

代码随想录 图论

目录 797.所有可能得路径 200.岛屿数量 695.岛屿的最大面积 1020.飞地的数量 130.被围绕的区域 417.太平洋大西洋水流问题 827.最大人工岛 127.单词接龙 841.钥匙和房间 463.岛屿的周长 797.所有可能得路径 797. 所有可能的路径 中等 给你一个有 n 个节点的…

什么是V R美术馆|V R互动体验店加盟|虚拟现实元宇宙

VR美术馆是利用虚拟现实&#xff08;VR&#xff09;技术构建的数字化美术馆&#xff0c;通过虚拟展厅和虚拟展览等形式展示艺术作品、举办艺术展览&#xff0c;为用户提供一种沉浸式的艺术体验。用户可以通过穿戴VR头显等设备&#xff0c;在虚拟环境中自由浏览各种艺术作品&…

20240319-1-过拟合与欠拟合

过拟合欠拟合面试题 1. 如何理解高方差与低偏差? 模型的预测误差可以分解为三个部分: 偏差(bias)&#xff0c; 方差(variance) 和噪声(noise). 偏差 偏差度量了模型的期望预测与真实结果的偏离程度&#xff0c; 即刻画了学习算法本身的拟合能力。偏差则表现为在特定分布上…

RocketMq方便测试,提供一个controller的接口,支持拉取消息,查看消息内容

通过一个REST API接口动态地启动RocketMQ的消费者&#xff0c;并基于传入的参数&#xff08;topicName&#xff0c;filterExpression&#xff0c;consumerGroupId&#xff09;决定要监听哪些消息。在Spring Boot项目中&#xff0c;这通常不是推荐的做法&#xff0c;因为消息消费…

启动Hbase shell时有许多日志信息的解决办法

一、问题描述 在使用HBase时&#xff0c;当我们启动HBase shell时&#xff0c;会显示大量的日志信息&#xff0c;这些日志信息可能会干扰我们的操作&#xff0c;我们希望在启动HBase shell时不显示这些日志信息。 二、解决方案 方案一:修改配置文件 我们可以通过修改HBase的…