JS小技巧(一)持续更新

196 阅读3分钟

1 import引入

import * as enums from './enums'

将enums内的export都取出,使用直接调用.xxx方式

例如

enums.field

enums.a

2 将连字符 - 转换成小驼峰

'todo-list-yyy'.replace(/-(\w)/g, (_, c) => c ? c.toUpperCase() : '')
// 'todoListYyy'

3 检查变量是否是Object

如果使用typeof bar === "object" ,那么当bar为null的时候,也是返回true

所以使用

Object.prototype.toString.call()

Object.prototype.toString.call({a:1}) === '[object Object]'
// true
同样的如果是数组的话
Object.prototype.toString.call([]) === '[object Array]'
// 还可以是 正则,数字,字符串

原理

首先要知道,每个数据类型都有toString的方法,已经能够判断是什么数据类型,但是他是可以输出数据类型的,不利于判断

结果表现不一的原因在于:所有类在继承Object的时候,改写了toString()方法。

因此我们想判断数据类型时,也只能使用原始方法。继而有了此方法:Object.prototype.toString.call(obj)

4 判断对象中是否含有某个属性

通常使用obj.a===undefined来进行判断,但是对象中如果存在get和set的方法,这个就失效了,所以可以使用 判断对象中是否存在属性描述符进行判断。

const b={c:12,
        get foo(){
        	return 12
        },
         set foo(n){
         	 a=n
           this.c =n
         }
        }
const p =Object.getOwnPropertyDescriptor(b, 'foo')
if(p){
	......
}
// 如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor),否则返回 undefined

5 对象中隐藏的属性

对象中可以配置方法,get和set来改变值

let a =1
const b={c:12,
        get foo(){
        	return 12
        },
         set foo(n){
         	 a=n
           this.c =n
         }
        }
b.foo
// 12
b.foo=50
// a =50 ,b.c=50

value 该属性的值(仅针对数据属性描述符有效)

writable 当且仅当属性的值可以被改变时为true。(仅针对数据属性描述有效)

get 获取该属性的访问器函数(getter)。如果没有访问器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)

set 获取该属性的设置器函数(setter)。 如果没有设置器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)

configurable 当且仅当指定对象的属性描述可以被改变或者属性可被删除时,为true。

enumerable

当且仅当指定对象的属性可以被枚举出时,为 true。

6 call()、apply()、bind() 的用法

这三个函数的第一个参数都是 this 的指向对象,即改变函数this的指向

obj.objAge;  // 17
obj.myFun()  // 小张年龄 undefined

obj.myFun.call(db);    // 德玛年龄 99
obj.myFun.apply(db);    // 德玛年龄 99
obj.myFun.bind(db)();   // 德玛年龄 99

这三者的区别,传参形式不同

obj.myFun.call(db,'成都','上海');     // 德玛 年龄 99  来自 成都去往上海
obj.myFun.apply(db,['成都','上海']);      // 德玛 年龄 99  来自 成都去往上海  
obj.myFun.bind(db,'成都','上海')();       // 德玛 年龄 99  来自 成都去往上海
obj.myFun.bind(db,['成都','上海'])();   // 德玛 年龄 99  来自 成都, 上海去往 undefined

7 同步异步

  • 当使用forEach遍历内部进行异步操作的时候,不会阻塞代码。

  • 想要里面多个个await都执行完,再遍历第二次。这是无法实现的

[1, 2, 3].forEach( async (value) => {
  console.log(value) 
    let foo = await promiseFn();
  console.log('123')// 不会受到异步阻塞,也就是会打印输出3次value,才到这里
  let foo = await promiseFn();
});

原因分析:

因为forEach实质上就是一个for循环,我们使用的时候没有对这个for循环里面的callback 进行async await 进行包裹

Array.prototype.forEach = function (callback) {
    for(let index = 0; index < this.length; index++) {
        callback(this[index], index, this);
    }
}

解决方法:

使用for进行遍历

async load(){
	for (let index = 0; index < this.result.length; index += 1) {
  		const el = this.result[index]
      const res = await db().queryDBData()
  }
}

8 Switch

  • 在一个 switch 块内,每个 case 要么通过 continue/break/return 等来终止,

  • 在一个 switch 块内,都必须包含一个 default 语句并且放在最后,即使它什么代码也没有。

  • 注意 break 是退出 switch 语句块(会执行switch后面的语句),而 return 是退出方法体(不会执行后面的函数)。

  • 如果是 for循环里面的if 要结束返回,使用break

9 every

判断数组每一项的值是否满足条件。若是一个空数组,无论如何都会返回 true

调用 every 之后添加到数组中的元素,不会被执行

[].every(i=>i==3)
// true

解构赋值的连续写法

const param={id:{a:1,b:2}}
const {id:{a,b}}=param
// console.log(a,b)
// 1,2

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天

点击查看活动详情