ES6系列学习(5)

1.Promise简介

回调中使用回调函数,保证执行顺序:

在这里插入图片描述

let username;
const usersPromise = axios.get('https://api.github.com/users');

usersPromise.then(reponse => {
	username = response.data[0].login;
	return axios.get('https://api.github.com/users/${username}/repos');
}).then(reponse =>{
	console.log(reponse.data);
})
.catch(err =>{
	console.log(err)
})

2.构建一个Promise

//成功之后利用resolve发送数据到.then,失败之后利用reject发送数据到.catch
const p = new Promise((resolve,reject) => {
	resolve('成功了');
	reject(Error('失败了'));
})
p.then(data => {console.log(data)})
.catch(err => {console.log(err)})

参考文章:
https://www.cnblogs.com/soyxiaobi/p/9400331.html
https://www.cnblogs.com/huansky/p/6064402.html
https://www.jianshu.com/p/c77cfde7ebe1

3.Promise实例应用

function getRepoById(id){
	return new Promise((resolve,reject) => {
		const repo = repos.find(repo => repo.id === id);
		if(repo){
			resolve(repo);
		}else{
			reject(Error('No repo found.'));
		}
	})
}

getRepoById(1).then(repo => {
	console.log(repo)
}).catch(err => {
	console.log(err)
})

4.处理多个Promise

const usersPromise = new Promise(

);

const moviePromise = new Promise(

);

Promise.all([usersPromise ,moviePromise ])
.then(responses =>{
	console.log(responses);   //返回的是一个数组,包含两个Promise的结果
	const [users,movie] = responses;
	console.log(users);
	console.log(movie);
}).catch(err => {
	console.log(err)
})

还有Promise.race(),哪个运行的快运行哪个。

5.Symbol

如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。

Symbol 值通过Symbol函数生成。

这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

let s1 = Symbol()
let s2 = Symbol('another symbol')
let s3 = Symbol('another symbol')

s1 === s2 // false
s2 === s3 // false

注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。

Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。

let s1 = Symbol('foo');
let s2 = Symbol('bar');

s1 // Symbol(foo)
s2 // Symbol(bar)

s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"

上面代码中,s1和s2是两个 Symbol 值。如果不加参数,它们在控制台的输出都是Symbol(),不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。

应用场景1:使用Symbol来作为对象属性名(key)

来看一些应用和Object.keys()、in和getOwnPropertyNames操作:

let obj = {
   [Symbol('name')]: '一斤代码',
   [Symbol('name')]:'二斤代码',
   age: 18,
   title: 'Engineer'
}

const classRoom = {
	[Symbol('lily')]:{grade:68},
	[Symbol('nina')]:{grade:80},
	[Symbol('nina')]:{grade:90},
}

Object.keys(obj)   // ['age', 'title']

for (let p in obj) {
   console.log(p)   // 分别会输出:'age' 和 'title'
}

Object.getOwnPropertyNames(obj)   // ['age', 'title']

由上代码可知,Symbol类型的key是不能通过Object.keys()或者for…in、getOwnPropertyNames来枚举的(非enum),它未被包含在对象自身的属性名集合(property names)之中。所以,利用该特性,我们可以把一些不需要对外操作和访问的属性使用Symbol来定义。

也正因为这样一个特性,当使用JSON.stringify()将对象转换成JSON字符串的时候,Symbol属性也会被排除在输出内容之外:

JSON.stringify(obj)  // {"age":18,"title":"Engineer"}

我们可以利用这一特点来更好的设计我们的数据对象,让“对内操作”和“对外选择性输出”变得更加优雅。

然而,这样的话,我们就没办法获取以Symbol方式定义的对象属性了么?非也。还是会有一些专门针对Symbol的API,比如:

// 使用Object的API
Object.getOwnPropertySymbols(obj) // [Symbol(name)]

// 使用新增的反射API
Reflect.ownKeys(obj) // [Symbol(name), 'age', 'title']

应用场景2:使用Symbol来替代常量

我们先看下面代码:

const TYPE_AUDIO = 'AUDIO'
const TYPE_VIDEO = 'VIDEO'
const TYPE_IMAGE = 'IMAGE'

function handleFileResource(resource) {
  switch(resource.type) {
    case TYPE_AUDIO:
      playAudio(resource)
      break
    case TYPE_VIDEO:
      playVideo(resource)
      break
    case TYPE_IMAGE:
      previewImage(resource)
      break
    default:
      throw new Error('Unknown type of resource')
  }
}

如上面的代码中那样,我们经常定义一组常量来代表一种业务逻辑下的几个不同类型,我们通常希望这几个常量之间是唯一的关系,为了保证这一点,我们需要为常量赋一个唯一的值(比如这里的’AUDIO’、‘VIDEO’、 ‘IMAGE’),常量少的时候还算好,但是常量一多,你可能还得花点脑子好好为他们取个好点的名字。

现在有了Symbol,我们大可不必这么麻烦了:

const TYPE_AUDIO = Symbol()
const TYPE_VIDEO = Symbol()
const TYPE_IMAGE = Symbol()

这样定义,直接就保证了三个常量的值是唯一的了!是不是挺方便的呢。

应用场景3:使用Symbol定义类的私有属性/方法

我们知道在JavaScript中,是没有如Java等面向对象语言的访问控制关键字private的,类上所有定义的属性或方法都是可公开访问的。因此这对我们进行API的设计时造成了一些困扰。

而有了Symbol以及模块化机制,类的私有属性和方法才变成可能。例如:

在文件 a.js中

const PASSWORD = Symbol()

class Login {
  constructor(username, password) {
    this.username = username
    this[PASSWORD] = password
  }

  checkPassword(pwd) {
      return this[PASSWORD] === pwd
  }
}

export default Login

在文件 b.js 中

import Login from './a'

const login = new Login('admin', '123456')

login.checkPassword('123456')  // true

login.PASSWORD  // oh!no!
login[PASSWORD] // oh!no!
login["PASSWORD"] // oh!no!

由于Symbol常量PASSWORD被定义在a.js所在的模块中,外面的模块获取不到这个Symbol,也不可能再创建一个一模一样的Symbol出来(因为Symbol是唯一的),因此这个PASSWORD的Symbol只能被限制在a.js内部使用,所以使用它来定义的类属性是没有办法被模块外访问到的,达到了一个私有化的效果。

参考文章:https://www.jianshu.com/p/f40a77bbd74e

6.ESlint

ESlint是可组装的JavaScript和JSX检查工具。

全局安装eslint之后,使用eslint --init,生成.eslintrc.json这个配置文件,我们看下一些配置:

{
    "rules": {
"no-console": 2, // 禁用 console
"no-alert": 2, // 禁用 alert
"no-irregular-whitespace": 2, //禁止tab、空格之外的非法空白
"no-unexpected-multiline": 2, //禁止使用令人困惑的多行表达式,一行结束最后使用;或者是- +之类的连接符
"guard-for-in": 2, // for in 循环必须限制 Object.prototype.hasOwnProperty
"no-caller": 2, //禁用 arguments.caller 或 arguments.callee
"no-extend-native": 2, //禁止扩展原生对象
"no-extra-bind": 2, //禁止不必要的函数绑定 函数中没有使用this时,不需要绑定this
"no-invalid-this": 1, // 控制this的使用,只能在构造函数【首字母大写】、对象、类中使用
"no-multi-spaces": [2, {"ignoreEOLComments": true}], //禁止非缩进处出现多个空格 ,但忽略行尾注释前的多个空格 let a =   b; b前空格多了
"no-multi-str": 2, //禁止多行字符串 \ 可以连接多行字符实现换行,建议使用 '\n' +的组合
"no-new-wrappers": 2, //禁止原始包装实例 new String new Number的操作不合理,会变成初始化一个对象,而不是对应的初始类型
"no-throw-literal": 2, //限制可以被抛出的异常 仅仅 抛出(throw) Error 对象本身或者用户自定义的以 Error 对象为基础的异常
"no-with": 2, //不使用with
"no-unused-vars": [2, {"args": "none"}], // 未使用的变量定义,参数不校验,参数有可能是可选参数
"array-bracket-spacing": [2, "never"], //禁止或强制在括号内使用空格, 禁止使用不一致的空格,应该遵守格式 [1, 2, 3],也就是,逗号后面一个空格
"brace-style": 2, //大括号风格要求 one true brace style 风格如下:
/*
if (foo) {
  bar();
} else {
  baz();
}
*/
"camelcase": [1, {"properties": "never"}], // 驼峰变量命名,警告,而且属性名不会要求是驼峰,变量名要求是
"comma-dangle": [2], //禁止在数组、对象、函数参数最后面添加拖尾逗号
"comma-spacing": 2, // 逗号后非行尾需要加空格
"comma-style": 2, //要求逗号放在数组元素、对象属性或变量声明之后,且在同一行 
"computed-property-spacing": 2, //禁止在计算属性中使用空格 obj[key] ok
"eol-last": 2, //要求在非空文件末尾至少存在一行空行
"func-call-spacing": 2, // 函数执行需要紧挨着(括号,alert(1) ok 不要alert  (2)
"jsx-quotes": 2, //强制所有不包含双引号的 JSX 属性值使用双引号
"key-spacing": 2, // 对象key之后,冒号前不允许有空格; value前需要有空格
"keyword-spacing": 0, //要求在关键字之前、之后都至少有一个空格
"linebreak-style": 2, //强制使用 Unix 换行符: \n
"new-cap": 2, //要求构造函数首字母大写
"newline-after-var": 1, // 变量定义后增加空行 warn
"no-array-constructor": 2, // new Array X 禁用 Array 构造函数
"no-mixed-spaces-and-tabs": 2, // 禁止混用tab与空格 禁止空格和 tab 的混合缩进
"no-multiple-empty-lines": [2, {"max": 2}], // 不能有多个空行,最多两行
"no-new-object": 2,  //禁用 Object 的构造函数
"no-trailing-spaces": 2, // 行尾不留空格
"object-curly-spacing": 2, //不允许花括号中有空格
"one-var-declaration-per-line": 2, // 一个var定义多个变量时每个变量必须换行
"padded-blocks": [2, "never"], // 其中一条:{}内第一行与最后一行不允许有空行
"quote-props": [2, "consistent"], //对象的属性名需要统一【 双引号、单引号、不加】三个选一
"quotes": [2, "single", {"allowTemplateLiterals": true}],
"semi-spacing": 2, // 分号前不加空格
"semi": 2, // 该有分号的地方都加分号
// "sort-keys": 1, //对象的键名需要按照字典序排序
// "sort-vars": 1, //变量定义按照字典序排序
"space-before-blocks": 2, // {} 前必须有空格,例如 function() {}
"space-before-function-paren": [2, "never"], // function 参数前不允许有空格
"spaced-comment": [2, "always"], // 注释后面//后需要增加空格
"arrow-parens": [2, "always"], // 要求箭头函数的参数使用圆括号
"constructor-super": 2, // 派生类中的构造函数必须调用 super()。非派生类的构造函数不能调用 super()。[字面量继承其他类的类就是派生类]
"generator-star-spacing": [2, "after"], // 约束 generator 函数强制在 * 和函数名之间有空格
"no-new-symbol": 2, // disallow new operators with the Symbol object 不要new symbol
"no-this-before-super": 2, // 禁止在构造函数中,在调用 super() 之前使用 this 或 super
//"no-var": 1, // 要求使用 let 或 const 而不是 var
//"prefer-rest-params": 1, // require rest parameters instead of arguments
"prefer-spread": 2, // 要求使用扩展运算符而非 .apply() ,参数在一个数组中时
"rest-spread-spacing": 2, // rest参数、扩展运算符 和其对应的表达式都不能有空格 ...args
"yield-star-spacing": [2, "after"], // 强制在 * 和 参数之间有空格 yield* other();
"no-debugger": "error", // 禁用 debugger
"no-sequences": "error", // 禁用逗号操作符
"no-dupe-args": "error", // 禁止 function 定义中出现重名参数
"no-inner-declarations": "error", // 禁止在嵌套的块中出现 function 声明 ;if等块中声明函数
 "no-unreachable": "error", // 禁止在return、throw、continue 和 break 语句之后出现不可达代码
"no-octal": "error", // 禁用八进制字面量 0开头的数字
"no-dupe-keys": "error", // 禁止对象字面量中出现重复的 key
"block-scoped-var": 2, // if,for内无var定义,可以用let // 强制把变量的使用限制在其定义的作用域范围内
"indent": [2, 4, {
      "SwitchCase": 1
    }],  // 统一缩进4字符,switch case需要缩进
"max-nested-callbacks": [2, 5], // 强制回调函数最大嵌套深度 5层
}
}

参考文章:
https://segmentfault.com/a/1190000009077086/
https://segmentfault.com/a/1190000011451121

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值