技术标签: html5 前端 es6 js Work-JavaScript javascript
Symbol 的值是唯一的,用来解决命名冲突的问题
Symbol 值不能与其他数据进行运算
Symbol 定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys 来获取对象的所有键名
- 代码例:
// 创建Symbol
let s = Symbol()
console.log(s, typeof s) // Symbol() 'symbol'
// 创建Symbol时写入名称,相当于注释名
let s2 = Symbol('name')
let s3 = Symbol('name')
console.log(s2 === s3) // false,每个symbol都是唯一的,不会完全相等
// Symbol.for创建
let s4 = Symbol.for('age')
let s5 = Symbol.for('age')
console.log(s4 === s5) // true,Symbol.for创建的,只要其中的标识值相同,例:'age',那么被创建的symbol就完全相等
// 创建的symbol不能进行运算,以下操作都会报错
let res1 = s + 100
let res2 = s > 100
let res3 = s + '你好'
- 代码例:
let obj = {
...}
// 在不知道以上对象中含有哪些属性时,使用Symbol对其创建属性
// 可以保证绝对的唯一性,且不会对原本对象里的属性造成影响
// 方法1
let methods = {
fn: Symbol(),
fn2: Symbol()
}
obj[methods.fn] = function() {
console.log('fn()')
}
obj[methods.fn2] = function() {
console.log('fn2()')
}
// 方法2
let obj2 = {
name: 'sky',
[Symbol('fn')]: function(){
console.log('fn()')
},
[Symbol('fn2')]: function(){
console.log('fn2()')
}
}
Symbol内置了11种值,这些值指向语言内部使用的方法,不同的方法会在特定的场景下自动执行。
方法名 | 说明 |
---|---|
Symbol.hasInstance | 当其他对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法 |
Symbol.isConcatSpreadable | 对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时,是否可以展开。 |
Symbol.species | 创建衍生对象时,会使用该属性 |
Symbol.match | 当执行 str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。 |
Symbol.replace | 当该对象被 str.replace(myObject)方法调用时,会返回该方法的返回值。 |
Symbol.search | 当该对象被 str.search (myObject)方法调用时,会返回该方法的返回值。 |
Symbol.split | 当该对象被 str.split(myObject)方法调用时,会返回该方法的返回值。 |
Symbol.iterator | 对象进行 for…of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器 |
Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。 |
Symbol. toStringTag | 在该对象上面调用 toString 方法时,返回该方法的返回值 |
Symbol. unscopables | 该对象指定了使用 with 关键字时,哪些属性会被 with环境排除。 |
- 代码例:
// 声明数组
const arr = ['sky', 'tom', 'jack', 'joe']
// for...in
for(let i in arr){
console.log(i) // 返回数组索引下标,依次输出 0 1 2 3
}
// for...of
for(let j of arr){
console.log(j) // 返回数组内的每个值,依次输出 'sky' 'tom' 'jack' 'joe'
}
对象进行 for…of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器
实现原理:
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
- 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
- 每调用 next 方法返回一个包含 value 和 done 属性的对象
- 代码例:
// 声明数组
const arr = ['sky', 'tom', 'jack', 'joe']
// arr数组有个Symbol.iterator方法,我们用一个变量来接收这个方法的返回结果
let iterator = arr[Symbol.iterator]()
// 而这个返回对象内,有个next方法
// 执行该方法会依次指向该数据结构内的成员,返回一个包含value和done属性的对象
console.log(iterator.next()) // {value: 'sky', done: false}
console.log(iterator.next()) // {value: 'tom', done: false}
console.log(iterator.next()) // {value: 'jack', done: false}
console.log(iterator.next()) // {value: 'joe', done: false}
console.log(iterator.next()) // {value: undefined, done: true}
- 代码例:
// 创建一个对象,包含数组
const obj1 = {
name: 'sky',
arr: ['joe', 'tom', 'jack', 'bob']
}
// 遍历该对象
for(let i of obj1){
console.log(i)
}
// 由于for...of遍历的是数组,无法直接遍历对象,因此以上代码会报错
// 我们需要在该对象中自定义需要遍历的数组,才能遍历返回正确结果
// 创建一个对象,包含数组
const obj2 = {
name: 'sky',
arr: ['joe', 'tom', 'jack', 'bob'],
// 在需要遍历的对象内,自定义创建Symbol.iterator方法
[Symbol.iterator]() {
// this指向
let _this = this
// index索引变量
let index = 0
// 需要遍历的数组长度
let length = this.arr.length
// Symbol.iterator方法内会返回一个对象
return{
// 返回对象内包含一个next方法
next(){
// next方法内自定义需要遍历的数组对象
if(index < length){
// next 方法返回一个包含 value 和 done 属性的对象
const result = {
value: _this.arr[index], done: false}
// index自增
index++
// 返回对象
return result
}else{
return {
value: undefined, done: true}
}
}
}
}
}
// 遍历该对象
for(let j of obj2){
console.log(j) // 返回对象内arr数组的值,依次输出 'joe', 'tom', 'jack', 'bob'
}
生成器就是一个特殊的函数
- 代码例:
// 创建一个生成器函数,*号靠左靠右都没关系
function * gen(){
console.log('hello')
}
// 直接执行该函数,内部语句是不执行的
gen()
// 生成器函数的返回结果就是一个迭代器对象
let iterator = gen()
// 用其中的next方法才能运行语句
console.log(iterator.next()) // 'hello'
// yield分隔符,可以用来控制分隔每次执行next方法时,所需要执行的语句
function * gen2(){
console.log(111) // 第一次next方法执行的语句
yield '第一段执行完毕'
console.log(222) // 第二次next方法执行的语句
yield '第二段执行完毕'
console.log(333) // 第三次next方法执行的语句
yield '第三段执行完毕,还有最后一段未执行'
console.log(444) // 第四次next方法执行的语句
}
let iterator2 = gen2()
console.log(iterator2.next()) // {value: '第一段执行完毕', done: false}
console.log(iterator2.next()) // {value: '第二段执行完毕', done: false}
console.log(iterator2.next()) // {value: '第三段执行完毕', done: false}
console.log(iterator2.next()) // {value: undefined, done: true}
- 代码例:
// 创建生成器函数
function * gen(arg){
console.log(arg) // 'gen执行时的参数'
// 创建变量,接收next方法内的实参
let next2Arg = yield 1
console.log(next2Arg) // '第2次next的参数'
let next3Arg = yield 2
console.log(next3Arg) // '第3次next的参数'
let next4Arg = yield 3
console.log(next4Arg) // '第4次next的参数'
}
let iterator = gen('gen执行时的参数')
iterator.next()
// 第2次next方法开始可以传入实参
// 该实参由当前next方法所执行语句的前一个yield所接受
iterator.next('第2次next的参数')
iterator.next('第3次next的参数')
iterator.next('第4次next的参数')
- 代码例:
// 请求用户数据
function getUsers() {
setTimeout(()=>{
let data = '用户数据'
// 传入用户数据,执行下个next
iterator.next(data)
},1000)
}
// 请求订单数据
function getOrders() {
setTimeout(()=>{
console.log(users) // '用户数据'
let data = '订单数据'
// 传入订单数据,执行下个next
iterator.next(data)
},1000)
}
// 请求商品数据
function getGoods() {
setTimeout(()=>{
console.log(orders) // '订单数据'
let data = '商品数据'
// 传入商品数据,执行下个next
iterator.next(data)
},1000)
}
// 创建生成器函数
function * gen() {
// users 用户数据实参
let users = yield getUsers()
// orders 订单数据实参
let orders = yield getOrders()
// goods 商品数据实参
let goods = yield getGoods()
}
// 创建迭代器对象并调用next
let iterator = gen()
iterator.next()
- Recorded by Scorpio_sky@2021-01-17
文章浏览阅读75次。Java与世界的初次见面——Java产生史故事版 2021年的一天,这为29岁的工程师回到家中,放下手中的各种工具,静静地躺在贵妃榻上,望着窗外远方的山,端起手边的咖啡微抿一口,思绪又渐渐回到了30年前。那时的他刚刚出生,但根据这个世界的规定,未满三岁的新生儿不能够登记并拥有自己的名字,于是父母便临时给它起了一个名字叫Oak。Oak从小就要与众不同,他常常用自己与众不同的方法解决前辈们所处的各种问题,但就算如此,他依然没有得到前辈们的重视,只是像同辈们一样,渐渐长到了3岁,而就在他三岁的这..._special jiva actualiser of awareness
文章浏览阅读1.5k次。iphone隔空投送失败是什么原因?IOS系统下有两个并列又超级强大的功能就是Airplay屏幕镜像与AirDrop隔空投送,Airplay屏幕镜像,其实经常玩手机投屏的水果粉应该都知道,Airplay屏幕镜像可以进行多屏幕之间的一个互动功能,播放模式为镜像模式,也就是手机与投屏的大屏幕为同步显示状态。AirDrop隔空投送:(推荐学习:web前端视频教程)AirDrop是Apple在设备之间以无..._kepserver尝试添加项''失败
文章浏览阅读398次。1. Fine-tuning 微调 Transfer learningFine-tuning 微调是整个深度学习领域是最重要的技能。如果前面的知识只能选择一个,那就是微调了。Transfer learning迁移学习,就是可以用别的成功网络的参数等来训练跟你相似的模型。简单来说是重用。跟详细知识请参考: Transfer learning 迁移学习指南2. 代码实现3. Q&Afine tuning和transfer training实际上是同_finetune——transfer
文章浏览阅读1.7k次。我正在使用python docx库来操作word文档.但是我找不到该库的文档页面中的一条线与中心对齐.我也找不到Google.from docx import Documentdocument = Document()p = document.add_paragraph('A plain paragraph having some ')p.add_run('bold').bold = Truep...._python-doc table 右对齐
文章浏览阅读235次。Spark也有数据本地化的概念(Data Locality),这和MapReduce的Local Task差不多,如果读取HDFS文件,Spark则会根据数据的存储位置,分配离数据存储最近的Executor去执行任务。这么理解没错,我搭建的Spark集群情况是这样:每台DataNode节点的HDFS集群,我在每个DataNode上都部署了一个Spark Worker,并且,启动Spark Ap..._任务本地化源码
文章浏览阅读2.6k次。世界最顶级邮件服务器组合Linux + PMTA + OEMPRO PowerMTA 安装PMTA + OEMPRO 这个是发送的组合 PMTA提供的SMTP,OEMPRO是订阅管理以及邮件的过滤等SPF, DKIM, Sender-ID, DNS, rDNS 这些各自有分工, 分别在DNS解析和联系主机商进行解析。pmta+iem是世界顶级的邮件服务器,每天单台服务器可投递百万级邮件,..._powermta 收件箱在哪个文件夹
文章浏览阅读5.2k次。swiper作为一个开源的前端组件,主要用来做各种页面切换轮播的效果。在做左右切换效果时,发现点击左右箭头没有效果,原来是需要在左右箭头的页面标签上添加点击事件才行,代码如下,亲测可用<swiper ref="mySwiper" :options="swiperOptions"> <swiper-slide><div style="background-color: #5cb85c;height: 100%"><img src=_vue cursor: pointer 不生效
文章浏览阅读2.4w次,点赞10次,收藏25次。Unity一键打包工具,一键生成几十个平台/渠道的安装包。_unity混淆工具obfuscar
文章浏览阅读1.1k次。https://github.com/lucasec/mdns-repeater代码来自上面的链接,这个东西有什么用处了1:模仿程序,可以显示多播数据的转发2:对 mDNS的数据进行转发3: 多播数据是无法穿越路由NAT,如 openwrt中的WAN和LAN对于的网络接口4:mdns-repeater 使用直接 接网络接口名称mdns-repeatereth0 br-lan 就可以实现数据在接口之间的转发5:mDNS 的简介mDNS , multicast DN.....
文章浏览阅读8.5w次,点赞68次,收藏147次。有时候从网上下载的数据集扩展名(后缀名)是npz,我们需要对数据进行加载(读取):例如:识别猫狗图片的二分类,下的数据集分别为cat.npz和dog.npzimport numpy as npcat_data = np.load(‘cat.npz’)dog_data = np.load(‘dog.npz’)因为以npz结尾的数据集是压缩文件,里面还有其他的文件使用:cat_data.f..._查看npz结构
文章浏览阅读7.2k次,点赞26次,收藏18次。《异常检测——从经典算法到深度学习》0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: 基于 VAE 的 Web 应用周期性 KPI 无监督异常检测9 基于条件 VAE 的鲁棒无监督KPI异常检测2018 Robust and Unsupervised K_robust and unsupervised kpi anomaly detection based on conditional variation
文章浏览阅读1.1w次,点赞3次,收藏2次。不能直接存为SLDDRT,要先存为(*.DRWDOT),然后使用“文件”→“保存图纸格式”,保存为可以在工程图中可以查找到的模板文件。_slddrt