快捷搜索:  汽车  科技

对javascript的认识和理解(现代JavaScript的高级概念和用法)

对javascript的认识和理解(现代JavaScript的高级概念和用法)const fruits = ["apple" null "mongo" undefined ""] const filted = fruits.filter(boolean) console.debug(filted) //(2) ["apple" "mongo"] const any = fruits.some(Boolean) console.log(any) //true消除重复值const fruits = ["apple" null "mongo" "apple" ""] const uniqued = [...new Set(fruits)] console.debug(uniqued) //(4) ["a

对javascript的认识和理解(现代JavaScript的高级概念和用法)(1)

JavaScript语言不断发布一些新特性,感觉要上天的节奏啊。本文搜集整理了一些它的高级概念和用法,来看看你是否都了解?代码这样写是不是更优雅了?

闭包

闭包是Javascript中的一项重要技术,内部函数始终可以访问其外部函数的变量和参数,即使在外部函数返回后也是如此。我们使用闭包来保护我们不想向外部范围公开的数据。

// <button onclick=”increaseCounter()”>Increase Counter</button> //1. 全局变量,变量会被意外修改 let counter = 0; function increaseCounter() { counter ; } //2. 局部变量,每次调用都重置为0 function increaseCounter() { let counter = 0; counter ; } //3. 闭包函数,符合要求 const increaseCounter = (function() { let counter = 0; return function() { counter = counter 1; console.log(counter); }; })();函数绑定

在上下文丢失时,this将无法被确定,可以通过函数绑定解决。

// 1. 与预期不符,得到undefined let book = { title: ‘Learn JavaScript’ printTitle() { console.log(`Book’s title: ${this.title}`); } } setTimeout(book.printTitle 1000); // Book’s title: undefined // 2. 利用函数绑定,符合预期 let book = { title: ‘Learn JavaScript’ printTitle() { console.log(`Book’s title: ${this.title}`); } } let printTitle = book.printTitle.bind(book); setTimeout(printTitle 1000); // Book’s title: JavaScript使用命名空间

使用命名空间可以防止代码冲突。

// 1. move、jump函数在animal命名空间下,需要通过animal.move()来调用 let animal = { move: () => { console.log(‘Move!’); } jump: () => { consle.log(‘Jump!’); } }; // 2. 真实项目中,可能会按如下方式使用命名空间 if (typeof APP === "undefined") { APP = {}; APP.ANIMAL = {}; } APP.ANIMAL.move = () => { console.log(‘Move’); }; APP.ANIMAL.jump = () => { console.log(‘Jump’); }; APP.ANIMAL.move(); // Move APP.ANIMAL.jump(); // Jump判断属性是否存在

使用in关键字可以判断对象中是否存在某个属性。

const person = { id: "123" name: "张三" } console.debug("id" in person) //true console.debug("age" in person) //false解构赋值

利用解构赋值表达式,可以将属性、值从对象、数组中取出,赋值给其它变量,非常方便。

const { address: addressLine } = { address: "长安街20号" postcode: "518118" }; console.warn(addressLine); // 长安街20号 const [first second] = [1 2 3 4] console.warn(first second) // 1 2 //动态解构 const extractKey = "postcode" const { [extractKey]: youbian } = { address: "长安街20号" postcode: "518118" }; console.log(youbian) //518118遍历对象属性

使用Object.entries可以遍历对象的属性和值。

const data = { address: "长安街20号" postcode: "518118" }; Object.entries(data).forEach(([key value]) => { if (["address" "postcode"].includes(key)) { console.log('key:' key 'value:' value) } }) //输出结果如下 key: address value: 长安街20号 key: postcode value: 518118过滤数组

利用数组的filter、some对数组进行筛选。

const fruits = ["apple" null "mongo" undefined ""] const filted = fruits.filter(boolean) console.debug(filted) //(2) ["apple" "mongo"] const any = fruits.some(Boolean) console.log(any) //true消除重复值

const fruits = ["apple" null "mongo" "apple" ""] const uniqued = [...new Set(fruits)] console.debug(uniqued) //(4) ["apple" null "mongo" ""]判断是否数组

利用Array.isArray,而不是typeof判断。

const fruits = ["apple" null "mongo" "apple" ""] console.debug(typeof fruits) //object console.error(Array.isArray(fruits)) //true转换数字和字符串

const text = "12345" console.debug("text:" text "typeof:" typeof( text)) //text:12345 typeof:number const num = 123456 console.debug("number:" num "" "typeof:" typeof(num "")) //number:123456 typeof:string转换为boolean

利用!!运算符可以将其它类型转换为Boolean类型。

console.log(!!null typeof(!!null)) //false boolean console.log(!!"" typeof(!!"")) //false boolean console.log(!!undefined typeof(!!undefined)) //false boolean console.log(!!null typeof(!!null)) //false boolean console.log(!!true typeof(!!true)) //true boolean console.log(!!false typeof(!!false)) //false boolean console.log(!!{id:"" name:""} typeof(!!{id:"" name:""})) //true boolean可选链

可选链 ?. 是一种访问嵌套对象属性的安全的方式,可避免在对象或属性不可用时抛出异常。由于JavaScript不是类型化语言,该特性还是很有用。

//未使用可选链接,将抛出异常 const contactInfos = { address: "长安街20号" }; console.warn(contactInfos.user.phoneNumber) // 以上语句将报错:Cannot read properties of undefined (reading 'phoneNumber') //使用可选链接,将打印undefined const contactInfos = { address: "长安街20号" }; console.warn(contactInfos.user?.phoneNumber) // undefined合并运算符

合并运算符的写法为两个问号 ??,对于该运算符连接的两个参数,如果第一个参数不是 null,也不是undefined,则返回第一个参数,否则返回第二个参数。

const contactInfos = { address: "长安街20号" }; console.warn(contactInfos.user?.phoneNumber ?? "") // "" const contactInfos = { address: "长安街20号" addressNumber: 0 }; console.warn(contactInfos.addressNumber || undefined) // undefined console.warn(contactInfos.addressNumber ?? undefined) // 0有条件地添加属性

使用...扩展语法,可以仅当某个条件成立时,才为对象添加某个属性。

const moreInfos = { info: "请开车前往." } return { address: "长安街20号" postcode: "518118" ...(moreInfos !== undefined && { moreInfos }) //仅当moreInfos不是undefined时,才添加moreInfos属性 }异步调用异常捕获

以下写法让处理异步调用异常的代码变得更为简洁。

const results = await getPosts().catch((err) => { return { type: "error" message: err.message } }); console.warn(results) // { type: "error" message: "cannot get posts from this endpoint" }弱引用Map

Weakmap不同于Map,它的键必须是引用对象,不能是基础类型,如果没有对该键对象引用时,该对象将被从Map和内存中移除。

const videosegments = new WeakMap() let options = { id: "1234" timeStart: 1653831957378 size: 10000 } const segment = { data: new Uint8Array(200) } videoSegments.set(options segment) console.warn(videoSegments.get(options)) // { data: new Uint8Array(200) } //以下当options被赋值为null后,该对象将被移除和回收 options = null console.warn(videoSegments.has(options)) // false the `options` key object is deleted from the WeakMap反射

Reflect是一个全局对象,它为元编程提供了一些有用的静态方法。

const person = { name: 'Bob' [Symbol('email')]: 'bob@evil.com' }; Reflect.get(person 'name'); // = Bob Reflect.has(person 'email'); // = true Reflect.has(person 'phone'); // = false Reflect.getPrototypeOf(person); // = { constructor ... } Reflect.getOwnPropertyDescriptor( person 'name'); // = { value: 'Bob' writable: true enumerable: true configurable: true } Reflect.ownKeys(person); // name Symbol(email) Reflect.defineProperty(person 'phone' { writable: true }); Reflect.has(person 'phone'); // = true Reflect.set(person 'phone' '123456789'); Reflect.deleteProperty(person 'phone'); Reflect.has(person 'phone'); // = false柯里化

柯里化(Currying)是一种关于函数的高阶技术,它是指将一个函数从可调用的 f(a b c) 转换为可调用的 f(a)(b)(c)。柯里化不会调用函数,它只是对函数进行转换。

// 完成银行转账交易函数,余额 转入金额-费用 const transaction = (fee balance amount) => ( balance amout - fee; ); // 简单实现的柯里化函数 const curry = (fn ...args) => ( (..._arg) => ( fn(...args ..._arg) ) ); // 复用了transaction函数的免交易费函数 const freeTransaction = curry(transaction 0); freeTransaction(10 90); // = 100组合

组合是一种技术,其中一个函数的结果被传递到下一个函数,该函数被传递到下一个函数,依此类推......直到执行最终函数并计算出一些结果。函数组合可以由任意数量的函数组成。

//f 和 g 都是函数,x 是在它们之间通过“管道”传输的值 var compose = function(f g) { return function(x) { return f(g(x)); }; }; var toUpperCase = function(x) { return x.toUpperCase(); }; var exclaim = function(x) { return x '!'; }; var shout = compose(exclaim toUpperCase); shout("send in the clowns"); //=> "SEND IN THE CLOWNS!"

// 组合函数 const compose = (...fns) => x => fns.reduce((y f) => f(y) x); // 原函数 const addFee = amount => amount 2; const addDiscount = amount => amount - 5; // 函数组合 const composition = compose(addFee addDiscount)(100); console.log(composition) //97

猜您喜欢: