ES6高级技巧(四)
238
数字->二进制->补码->十进制
const bitwise = N => {
if (N < 2) {
return N == 0 ? 1 : 0
}
/*转化为二进制*/
let str = N.toString(2)
/*补码*/
let sb = ''
for (let i = 0; i < str.length; i++) {
sb += str.charAt(i) == '0' ? '1' : '0'
}
/*转化十进制*/
return parseInt(+sb, 2)
}
console.log(bitwise(10))
some
some的实现逻辑本身就是短路的,一旦返回true后续迭代就不再执行了
let arr = [1, 2, 3, 4, 5] let sum = '' arr.some(v=>{ sum+=v if (v == 3) { return true } }) console.log(sum)
如果continue和break同时存在
let arr = [1, 2, 3, 4, 5] let text = '' for (let v of arr) { if (v === 2) { continue } if (v === 4) { break } text += v + ',' } console.log(text) // "1,3,"
只用some处理
arr.some(val => { if (val == 2) { return //跳过 } if (val == 4) { return true } sum += val }) console.log(sum)
判断undefined
const isUndefined = value => value == void 0
let a;
console.log(isUndefined(a)) //true
合并对象
const isObject = value => toString(value) === '[object Object]'
const merage = (a, b) => {
for (let item in b) {
if (isObject(b[item])) {
a[item]=merage(a[item],b[item])
}else{
a[item]=b[item]
}
}
return a
}
去重value
const uniqueBy = (arr, fn) => {
return arr.filter((val, index, array) => {
return array.findIndex(item =>
typeof (fn) == 'function' ? fn.call(this, item) == fn.call(this, val)
: val[fn] == item[fn])
== index
})
}
递归逆序
const fun = num => {
let num1=num/10
let num2=num%10
if (!Math.floor(num1)) {
return num
}
if (Math.floor(num1)) {
return `${num2}`+fun(Math.floor(num1))
}
}
console.log(fun('12345'))
//不用递归,不用api
const fun = num => {
let end=num.length-1
let sum=''
while (end>=0) {
sum+=num[end]
end--
}
return sum
}
console.log(fun('12345'))
深度克隆
const isObject=obj=>Object.prototype.toString.call(obj) === '[object Object]'
const deepClone = (obj) => {
//基础数据类型是值传递
let arr = ['string', 'number', 'boolean', 'undefined']
if (arr.some(val => typeof obj == val)) {
return obj
}
//数组
let cobj;
if (Array.isArray(obj)) {
cobj = obj.map(val => deepClone(val))
}else{
if (isObject(obj)) {
let ret={};
for (let item in obj) {
ret[item]=deepClone(obj[item])
}
return ret
}
}
return cobj
}
console.log(deepClone({a:1,b:{a:1},c:3}))
禁止右键,选择,复制
// 鼠标右键事件 选择 复制
['contextmenu', 'selectstart', 'copy'].forEach(function (ev) {
document.addEventListener(ev, function (event) {
return event.preventDefault()
})
})
//event.preventDefault() 阻止默认的点击事件执行
判断是不是引用数据类型的数据
function isObject(value) {
let type = typeof value;
return value != null && (type == 'object' || type == 'function');
}
数据结构和算法是什么
数据结构是值一组数据的存储结构
算法就是操作数据的方法
数据结构和算法是相辅相成的,数据结构是为服务的,而算法要作用在特定的数据结构上
递归
//阶乘
const fact = n => {
if (n == 1) {
return n
}
return fact(n - 1) * n
}
console.log(fact(5))
//最大公约数
const gcd = (a, b) => {
if (b == 0) return a
return gcd(b, a % b)
}
console.log(gcd(5, 10))
// 走楼梯(一个台阶总共有n级台阶,如果一次可以跳1,2,
//问有多少种可能
const solve=n=>{
if(n==1) return 1
if(n==2) return 2
return solve(n - 1) + solve(n - 2)
}
console.log(solve(2))
//归并排序
const mergeSort = array => {
if (array.length < 2) return array
let mid = Math.floor(array.length / 2)
let left = array.slice(0, mid)
let right = array.slice(mid)
return merge(mergeSort(left), mergeSort(right))
}
const merge = (left, right) => {
let result = []
while (left.length > 0 && right.length > 0) {
if (left[0] < right[0]) {
result.push(left[0])
} else {
result.push(right[0])
}
}
return result.concat(left).concat(right)
}
852 山脉数组的峰顶索引
const pack=array=>{
let i=0
while (i < array.length - 1) {
if (array[i] > array[i+1]) {
return i
}
i++
}
return -1
}
console.log(pack([1, 8, 10, 4]))
Proxy
用于修改某些操作的默认行为,(拦截)(代理)
const proxy=new Proxy(target,hanler)
// target 表示拦截的对象,handler 是用来定制拦截行为的对象 let a = { name: 'zhangsan', age: 12 } let proxy = new Proxy(a, { //拦截读取的属性 get: (target, prop) => 35 }) console.log(proxy.name) //35
handler没有设置,等同于直接通向源对象
let proxy1 = new Proxy(a, {}) proxy1.a='b' console.log(a) //{ name: 'zhangsan', age: 12, a: 'b' }
Proxy实例的方法
get方法
接受三个参数:目标对象,属性名,proxy实例本身
let preson={ name:'zhangsan' } let proxy=new Proxy(preson,{ get:(target,props,p)=>{ if (props in target) { return target[props] }else{ return ('哥哥报错了') } } }) //如果没有拦截,访问不存在的属性,只会返回undefined console.log(proxy.aaa) //get方法可以继承 let p1=Object.create(proxy) console.log(p1.aaa) //get拦截,实现数组读取负数索引 const createArray = (...array) => { let target = [] target.push(...array) return new Proxy(target, { get: (target, prop) => { if (Number(prop) < 0) { prop = String(target.length + Number(prop)) } return Reflect.get(target,prop,p) } }) } let p = createArray('a', 'n', 'b') console.log(p[-2]) //n
set方法
接受四个参数,依次为目标对象,属性名,属性值,proxy实例本身
//设置一个对象不大于200且必须为整数 let preon=new Proxy({},{ set(target,prop,value){ if(prop=='age'){ if (value > 200||typeof(value)!='number') { throw new Error('报错了') } } } }) preon.age='a' console.log(p)
Reflect
Reflect 对象的方法与Proxy对象的方法一一对应
Reflect.get(target,props,args)
参数是(目标对象,属性,源对象)let myObjer={ foo:1, bar:2, get baz(){//get 函数的时候,会直接执行这个函数 return this.foo+this.bar } } console.log(Reflect.get(myObjer, 'foo'))//1 //改变this的指向从而改变这个值(源对象是用来改变this指向的) let a = { foo: 3, bar: 4 } console.log(Reflect.get(myObjer, 'baz', a))// 7
Reflect.set(target,prop,vlaue,args) 参数
目标对象,键,值,源对象
var myObject = { foo: 1, set bar(value) { return this.foo = value }, set(value) { return this.foo = value } } console.log(myObject.foo)//1 //原生方法 myObject.set(3) console.log(myObject.foo)//3 //Reflect.set Reflect.set(myObject, 'bar', 2) console.log(myObject.foo)//2 //改变this指向 //给属性设置赋值函数,则把赋值函数的this绑定给源对象(a) let a = { foo: 100//函数执行后,也就是this.foo=2 } Reflect.set(myObject, 'bar', 2, a) console.log(a.foo)//2
Reflect.has(target,prop)
Reflect.has 方法对应
prop in obj
let myObject={ foo:1 } //原生 console.log('foo' in myObject) //新写法 console.log(Reflect.has(myObject, 'foo')) //第一个参数不是对象会报错
Reflect.deleteProperty(target,prop)
等同于
delete target[prop]
用于删除对象的属性,如果target不是对象会报错let myObject={ foo:1 } //就写法 delete myObject.foo Reflect.deleteProperty(myObject,'foo') console.log(myObject)
Reflect.construct(target,args)
等同于new,如果target不是函数会报错
function Greeting(name) { this.name=name } const a=new Greeting('zhangsan') console.log(a.name) //new的另一种写法 const b=Reflect.construct(Greeting,['zhangsan']) console.log(b.name)
Reflect.getprototypeOf(target)
Reflect.getPrototypeOf
方法用于读取对象的__proto__
属性function Greeting(name) { this.name=name } const a=new Greeting('zhangsan') console.log(Object.getPrototypeOf(a) == Greeting.prototype) //新写法 console.log(Reflect.getPrototypeOf(a) == Greeting.prototype)
两个的区别
Reflect.getPrototypeOf
如果不是对象会报错
Object.getPrototypeOf
会把这个参数转为对象,然后再运行Reflect.setPrototypeOf(obj,newProto)
设置目标对象的原型
对应
Object.setPrototypeOf(obj,newProto)
,他返回一个布尔值,表示是否设置成功const myObj = {}; //原生 Object.setPrototypeOf(myObj,Array.prototype) //新写法 Reflect.setPrototypeOf(myObj,Array.prototype) console.log(myObj.length)//0
Reflect.apply(func,thisArg,args)
等同于
Function.prototype.apply.call()
const array = [1, 2, 3, 4, 4, 5] console.log(Math.max.apply(undefined,array)) //5 console.log(Math.max.apply(null,array)) //5 console.log(Object.prototype.toString.call([])) //[object Array] console.log(Reflect.apply(Math.min,undefined, array)) console.log(Reflect.apply(Object.prototype.toString,null, array))
Reflect.defineProperty(target,prop,attributes)
等同于
Object.defineProperty
function MyDate(){ } Object.defineProperty(MyDate,'num',{ value:()=>Date.now() }) console.log(MyDate.num()) Reflect.defineProperty(MyDate,'now',{ value:()=>Date.now() }) console.log(MyDate.now())
如果第一个参数不是对象,会报错
Reflect.getOwnPropertyDescriptor(target,prop)
用于得到指定属性的描述对象
let myObject={ name:'zhangsan' } //用于得到指定属性的描述对象 console.log(Object.getOwnPropertyDescriptor(myObject, 'name')) /*{ value: 'zhangsan', writable: true, enumerable: true, configurable: true }*/ //Reflect console.log(Reflect.getOwnPropertyDescriptor(myObject, 'name'))
Reflect.isExtensible(target)
方法等同于
Object.isExtensible
返回一个布尔值,表示当前对象是否扩展Reflect.ownKeys(target)
返回对象的所有属性
let a={ foo:1, bar:2 } Reflect.ownKeys(a)
前端开发规范
命名规范
- 目录命名
vue的项目,组件目录名,使用大驼峰命名
leftBar
JS,css,html文件命名:使用下划线
account_model.js
- HTML规范
属性上使用双引号
属性民全小写,用中划线(-)做分割符
不要再自动闭合标签结尾处使用斜线
<br>
数组方法
二分搜索
通过值查索引
const binarySearch = (arr, val, start = 0, end = arr.length - 1) => {
if (start > end) return -1;
const mid = Math.floor((end - start) / 2)
if (arr[mid] > val) return binarySearch(arr, val, start, mid - 1)
if (arr[mid] < val) return binarySearch(arr, val, start + 1, mid)
return mid
}
console.log(binarySearch([1, 3, 4, 4, 5, 6, 7, 8, 9, 12], 3))
算字符串的重复次数
算a,b,c,总共重复了多少次
const countStr = str => str.match(/[abc]/gi).length
console.log(countStr('abcabsssabc'))
求length=7的斐波那契的数组
const fibonacciUntilNum = num => {
return Array.from({ length: num })
.reduce(
(acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []
)
}
console.log(fibonacciUntilNum(10))
//[ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]
判断是不是Armstrong数
// a*a*a+b*b*b+c*c*c=abc 求出所有的这三个数,也叫Armstrong数
const isArmstrongNumber = digits => {
return (
arr => arr.reduce((acc, val) => acc + Number(val) ** arr.length, 0) == digits
)
(String(digits).split(''))
}
console.log(isArmstrongNumber(1634))
对象解构求值
const state = {
B: 2,
C: 1
};
const reducer3 = (state, payload) => {
return ({
...state,
B:state.B+payload,
C:state.C*payload
})
}
console.log(reducer3(state, 3))
!~
!~[1, 2, 3, 4, 5,].indexOf(8) //true
不存在就为true
其实可以用some
console.log(![1, 2, 3, 4, 5,].some(val => val == 9))
不调换顺序判断,第二个字符串字段是否包含第一个字符串的字段
const isStr = (target, str) => {
return [...str].reduce((acc, val) =>
val == (target[acc] || '') ? acc + 1 : acc
, 0) == target.length
}
console.log(isStr('ca', 'abc'))//false
console.log(isStr('ac', 'abc'))//true
查看原型是什么类型
const getType = v =>
[,null].some(val => val == v)
?v
:v.constructor.name.toLowerCase()
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬