您的位置:首页 > 汽车 > 新车 > 房地产市场低迷_网址有哪些组成_百度学术官网首页_seo教程技术

房地产市场低迷_网址有哪些组成_百度学术官网首页_seo教程技术

2024/12/27 9:00:56 来源:https://blog.csdn.net/weixin_62234646/article/details/144365986  浏览:    关键词:房地产市场低迷_网址有哪些组成_百度学术官网首页_seo教程技术
房地产市场低迷_网址有哪些组成_百度学术官网首页_seo教程技术

自 ECMAScript 2015 起,引入了一种新的基本类型 Symbol,在日常开发中,基本上用不到,使用场景很少,但是在面试中却深受面试官喜爱,一问一个不吱声。

今天我们就来了解一下这个 Symbol 类型。

Symbol

Symbol 和 Number、String 类似,是一个基本类型,表示一个独一无二的值,唯一的标识符。
可以使用 Symbol() 函数创建这种类型的值。

const sym = Symbol()
console.log(typeof sym)	// 'symbol'
Object.prototype.toString.call(sym)	// '[object Symbol]'

在 ES5 中,对象的属性名只有一种类型 String,现在 Symbol 类型的值也可以作为对象的属性名。
注意:

  • Symbol() 函数前不能使用 new 关键字,否则会报错。
new Symbol() // Uncaught TypeError: Symbol is not a constructor

这是因为生成的 symbol 是一个基本类型的值,不是一个对象。它与 string 类似,可以理解为字符串的额外扩展。

  • Symbol 不支持隐式转换。
    JavaScript 大部分值都能支持隐式转换。例如:我们可以 alert() 任何一个值,但 symbol 不行。
const sym = Symbol()
alert(sym) // Uncaught TypeError: Failed to execute 'alert' on 'Window': Cannot convert a Symbol value to a string
Symbol 的描述(description)

创建时,我们可以给 symbol 一个描述(也称为symbol名),descriptionSymbol 的一个静态属性。它是可选的,仅用于调试目的或转为字符串时进行区分,它访问的不是 symbol 本身。

const sym1 = Symbol("sym");	// sym1 是一个描述为 “sym” 的 symbol
const sym2 = Symbol("sym");console.log(sym1.description) // 'sym'
console.log(sym1 == sym2) // false

symbol 保证唯一,即使描述相同,它们的值也不一样。

如果想生成相同的 symbol 呢?也是可以的,ES6 提供了 Symbol.for() 方法,接受一个字符串作为参数,它会检索有没有以该参数为名称的 symbol,如果有直接返回值,否则重新创建一个。
Symbol.for() 创建的 symbol 会被登记在全局环境中以供搜索,我们可以通过 Symbol.keyFor() 返回已登记 symbol 的 key。

const sym1 = Symbol.for("symbol")
const sym2 = Symbol.for("symbol")console.log(sym1 == sym2) // true
console.log(Symbol.keyFor(sym1)) // 'symbol'

注意:
Symbol.For() 创建的 symbol 登记的 key,在全局作用域内都起作用。

function Sym() {return Symbol.for("symbol")
}const sym1 = Sym()
const sym2 = Symbol.for("symbol")
console.log(sym1 == sym2) // true

Symbol 的应用场景

1. 作为对象的键(key),防止属性值覆盖

在 ES5 中,一个对象如果出现了同名属性,后者会覆盖前者。

const obj = { a: 1, b: 2 }
Object.assign(obj, { a: 2 })
console.log(obj) // {a: 2, b: 2}

如果我们想要杜绝这种情况,避免意外覆盖的情况,这个时候就可以使用 ES6 中的 symbol 作为对象的键(key),因为它是唯一的。

const sym1 = Symbol("test")
const sym2 = Symbol("test")
const sym3 = Symbol("exam")
const obj = {[sym1]: "鱼钓猫",[sym2]: "的",[sym3]: "小鱼干"
}
console.log(obj) // {Symbol(test): '鱼钓猫', Symbol(test): '的', Symbol(exam): '小鱼干'}

但同时这会导致一个问题:

const obj = {cat: "鱼钓猫",fish: "小鱼干",[Symbol()]: "symbol"
}for(let k in obj) {console.log(k) // cat fish
}console.log(Object.keys(obj)) // ['cat', 'fish']
console.log(Object.getOwnPropertyNames(obj)) // ['cat', 'fish']

可以看到,正常的遍历或属性获取都会把 symbol 忽略掉。这里我们需要用 Object.getOwnPropertySymbol() 获取 symbol 键名。

console.log(Object.getOwnPropertySymbols(obj)) // [Symbol()]

如果想要全部返回,我们可以使用一个全新的 API Reflect.ownKeys() 。它返回对象的所有属性的集合,包含常规键和 symbol。

console.log(Reflect.ownKeys(obj)) // ['cat', 'fish', Symbol()]
2. 定义类的私有属性和方法

JavaScript 是一门弱类型语言,它的类型没有强制性,是没有类似 Java 等面向对象语言的访问对象关键字 private 的,类上的所有变量或方法都是可以公开访问的。
而由于使用 symbol 作为键名,不会被常规方法(for...infor...of)遍历得到,我们就可以基于这一特性,为对象定义一些非私有的、只用于内部的属性或方法,以达到保护私有属性的目的。

const exam = Symbol("exam")
class Test {constructor() {this[exam] = 0}add(v) {this[this[exam]] = vthis[exam]++}static sizeOf(instance) {return instance[exam]}
}const test = new Test() // 实例化一个 Test类
Test.sizeOf(test) // 0test.add("鱼钓猫") // test Test {0: '鱼钓猫', Symbol(exam): 1}
Test.sizeOf(test) // 1
Object.keys(test) // ['0']
Object.getOwnPropertyNames(test) // ['0']
Object.getOwnPropertySymbols(test) // [Symbol(exam)]

上面我们实例化一个 Test类 test,它的属性 exam 是一个 symbol值,所以 Object.keys()Object.getOwnPropertyNames() 都无法获取到属性 exam,这就形成了一个非私有的内部方法的效果。

3. 模块化机制

symbol 与模块化结合,可以更好的实现类的私有化。
exam.js

const EXAM = Symbol()class FishCat {constructor() {this.cat = "鱼钓猫"this.fish = "李东溪"this[EXAM] = 0}keys() {return Object.keys(this)}
}export default FishCat

tset.js

import FishCat from "./exam.js"const fishcat = new FishCat()
const sym = Symbol()/** 在这里无法访问到 exam.js 中的 symbol属性值 */
console.log(fishcat[Symbol()]) // undefined
console.log(fishcat.keys()) // [ 'cat', 'fish' ]/** 我们也可以在 test.js 中添加 symbol属性值 */
fishcat[sym] = "symbol"
fishcat.soul = "July"
console.log(fishcat.keys()) // [ 'cat', 'fish', 'soul' ]

当我们引入外部插件时,为了避免我们添加的属性方法和插件重写或意外操作,我们就可以使用 symbol值绑定,这样我们绑定的值就可以受到保护。

4. 生成器和迭代器

JavaScript 中使用了许多的系统 symbol,这些 symbol 可以通过 Symbol.* 来访问。我们可以使用它来改变一些内建行为,比如,我们可以使用 Symbol.iterator 来进行迭代操作,使用 Symbol.toPrimitive 来设置对象原始值的转换等等.

  • 生成器
  1. function 后跟 *
  2. yield关键字 后跟返回值,可以同步也可以异步
  3. next() 进行迭代,返回一个对象,done 为 false 表示继续迭代,为 true 表示迭代完毕。
function* gen() {yield Promise.resolve("鱼钓猫");yield "小鱼干";yield true;yield { name: "一棵松" };
}
const mm = gen()
console.log(mm.next()); // { value: Promise { '鱼钓猫' }, done: false }
console.log(mm.next()); // { value: '小鱼干', done: false }
console.log(mm.next()); // { value: true, done: false }
console.log(mm.next()); // { value: { name: '一棵松' }, done: false }
console.log(mm.next()); // { value: undefined, done: true }
  • 迭代器(Symbol.iterator)

伪数组都包含 Symbol.iterator,可以通过它进行迭代遍历。

// 这些是一些伪数组,都包含 Symbol.iterator
let set = new Set([1, 1, 2, 3, 3])
let map = new Map()
map.set('name', "鱼钓猫的小鱼干")
function args() {console.log(arguments);
}
let list = document.querySelectorAll('div')function each(data) {// 调用迭代器方法let Ite = data[Symbol.iterator]()let next = { done: false }while(!next.done) {next = Ite.next()if(!next.done) console.log(next.value);}
}console.log(each(set)) // 1 2 3 undefined
console.log(each(map)) // [ 'name', '鱼钓猫的小鱼干' ] undefined
  • 手动实现一个 Symbol.iterator

伪数组都是使用 Symbol.iterator 进行迭代,但是对象不是,我们可以手动实现一个。

let obj = {current: 0,max: 5,// 手动实现对象的 Symbol.iterator[Symbol.iterator]() {return {current: this.current,max: this.max,next() {if(this.current == this.max) { // 迭代结合return {value: undefined,done: true}} else {return {value: this.current++,done: false}}}}}
}
for(let val of obj) {console.log(val); // 0 1 2 3 4
}
console.log([...obj]); // [ 0, 1, 2, 3, 4 ]
console.log({...obj}); // { current: 0, max: 5, [Symbol(Symbol.iterator)]: [Function: [Symbol.iterator]] }

总结

Symbol 是 ES6 新增的一个基础类型,日常开发我们所用不多。
从技术上说,symbol 不是百分百隐藏的。有一个内建方法 Object.getOwnPropertySymbols() 允许我们获取所有的 symbol。还有一个名为 Reflect.ownKeys(obj) 的方法可以返回一个对象的所有键,包括 symbol。但大多数库、内建方法和语法结构都没有使用这些方法。

参考:
https://juejin.cn/post/6846687598249771022#heading-5
https://zh.javascript.info/symbol#yin-cang-shu-xing

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com