现代JavaScript的高级概念和用法

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

1. 闭包

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

//

//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);

};

})();2. 函数绑定

在上下文丢失时,念和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: JavaScript3.使用命名空间

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

// 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(); // Jump4. 判断属性是否存在

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

const person = {

id: "123",

name: "张三"

}

console.debug("id" in person) //true

console.debug("age" in person) //false5. 解构赋值

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

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) //5181186.遍历对象属性

使用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: 5181187. 过滤数组

利用数组的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) //true8. 消除重复值const fruits = ["apple", null, "mongo", "apple", ""]

const uniqued = [...new Set(fruits)]

console.debug(uniqued) //(4) ["apple", null, "mongo", ""]9. 判断是否数组

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

const fruits = ["apple", null, "mongo", "apple", ""]

console.debug(typeof fruits) //object

console.error(Array.isArray(fruits)) //true10. 转换数字和字符串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:string11. 转换为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, boolean12. 可选链

可选链 ?. 是一种访问嵌套对象属性的安全的方式,可避免在对象或属性不可用时抛出异常。由于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) // undefined13. 合并运算符

合并运算符的写法为两个问号 ??,对于该运算符连接的两个参数,如果第一个参数不是 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) // 014. 有条件地添加属性

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

const moreInfos = { info: "请开车前往." }

return {

address: "长安街20号",

postcode: "518118",

...(moreInfos !== undefined && { moreInfos }) //仅当moreInfos不是undefined时,才添加moreInfos属性

}15. 异步调用异常捕获

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

const results = await getPosts().catch((err) => {

return {

type: "error",

message: err.message

}

});

console.warn(results) // { type: "error", message: "cannot get posts from this endpoint" }16. 弱引用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 WeakMap17. 反射

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); // = false18. 柯里化

柯里化(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); // = 10019. 组合

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

//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
IT科技
上一篇:什么样的邮箱才是安全的电子邮件地址?
下一篇:为什么大家都选优质域名?到底存在着什么好处?