Node.js之10个JavaScript的最佳实践技能点(1)

43 阅读13分钟

图片 在 Node.js 中,有许多最佳实践可以帮助开发者编写更高效、更可靠的代码。在本文中,我们将介绍一些常见的最佳实践,比如const和let关键字、继承、计算型属性、类型转换和隐式类型转换,以及相等比较等,并提供一些实用的示例。

更多技术信息请关注公众号:CTO Plus,获取更多。

图片.png

原文:Node.js之10个JavaScript的最佳实践技能点(1)

1. 使用严格模式

在 JavaScript 中,可以使用"use strict" 指令启用严格模式。严格模式可以帮助开发者避免一些常见的错误,并提高代码的性能和安全性。

以下是一个使用严格模式的示例:

'use strict';

function myFunction() {
  // ...
}

2. 使用 const 和 let 关键字

在 ES6 中,引入了 const 和 let 关键字,可以帮助开发者更好地控制变量的作用域和生命周期。使用 const 声明的变量是不可变的,而使用 let 声明的变量是可变的。

以下是一个使用 const 和 let关键字的示例:

const PI = 3.14;

let count = 0;

function increment() {
  count++;
}

详细的特点和使用介绍,请参考公众号:CTO Plus中的文章《let 和 const 命令》 图片

3. 使用模块化编程

在 Node.js 中,可以使用模块化编程来组织代码并提高代码的可重用性和可维护性。可以使用 require() 函数来加载其他模块,并使用 module.exports 对象来导出模块。

以下是一个使用模块化编程的示例:

// math.js
function add(a, b) {
  return a + b;
}

module.exports = {
  add: add
};

// index.js
const math = require('./math');

console.log(math.add(1, 2));

详细的使用介绍,请参考公众号:CTO Plus中的文章《Node.js基础以及require、exports、module构建模块的基本属性详细介绍》 图片

4. 使用 Promise 和 async/await解决callback hell问题

在 Node.js 中,可以使用Promise 和 async/await 来处理异步操作。Promise可以帮助开发者更好地处理异步操作的结果,而 async/await 可以帮助开发者更好地处理异步操作的流程。

以下是一个使用 Promise 和async/await 的示例:

function fetchData() {
  return new Promise((resolve, reject) => {
    // ...
  });
}

async function myFunction() {
  try {
    const data = await fetchData();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

详细的使用介绍,请参考公众号:CTO Plus中的文章《Node.js异步编程之使用async控制并发详解与实战示例》和《Node.js异步编程之使用 promise 替代回调函数》。 图片

5. 使用 ESLint 进行代码检查

在 Node.js 中,可以使用ESLint 工具来检查代码风格和错误。ESLint 可以帮助开发者遵循最佳实践,并提高代码的可读性和可维护性。

以下是一个使用 ESLint 的示例:

{
  "rules": {
    "no-console": "error",
    "indent": ["error", 2],
    "quotes": ["error", "single"],
    "semi": ["error", "always"]
  }
}

关于ESLint的特点和详细使用介绍,参考公众号:CTO Plus中的文章《前端代码规范:前端代码规范扫描、代码自动编排工具-ESlint》。 图片

6. 继承

在 Node.js 中,继承是通过原型链实现的。在 JavaScript 中,每个对象都有一个原型对象,它包含了该对象的属性和方法。当我们访问一个对象的属性或方法时,如果该对象本身没有该属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的顶端。

Node.js 中的继承就是利用了原型链的特性。我们可以通过设置一个对象的原型对象来实现继承。

node 官方的 util

var util = require("util");
var events = require("events");

function MyStream() {
    events.EventEmitter.call(this);
}

util.inherits(MyStream, events.EventEmitter);

MyStream.prototype.write = function(data) {
    this.emit("data", data);
}

var stream = new MyStream();

console.log(stream instanceof events.EventEmitter); // true
console.log(MyStream.super_ === events.EventEmitter); // true

stream.on("data", function(data) {
    console.log('Received data: "' + data + '"');
})
stream.write("It works!"); // Received data: "It works!"

关于继承的内容详细使用介绍,参考公众号:CTO Plus中的文章《JavaScript面向对象编程》。 图片  

7. 计算型属性

JavaScript 中的计算型属性是指在访问对象的属性时,该属性的值不是在对象中预先定义好的,而是通过计算得到的。计算型属性有两种写法:

  • obj.value:这种写法是在对象中定义一个名为 value 的方法,当访问 obj.value 时,实际上是调用了这个方法并返回方法的返回值。

  • obj.value = xxx:这种写法是在对象中定义一个名为 value 的 setter 方法,当给 obj.value 赋值时,实际上是调用了这个 setter 方法,并将赋的值作为参数传递给这个方法。

类似Java中对象的属性定义 get 和 set 方法,通过 obj.valueobj.value= 的形式来调用。

const obj = {
    number: 0,

    get value(){
        return `${this.number}, ${Math.random()}`;
    },

    set value(newValue){
        this.number = newValue;
        console.log(`the new value is ${newValue}`);
    }
}

console.log(obj.value);
obj.value=1234;
console.log(obj.value);

图片

8. 类型转换

JavaScript 中的类型转换有两种:显式类型转换和隐式类型转换。

显式类型转换是指通过手动调用内置函数或者自定义函数来进行类型转换,例如使用Number()、String()、Boolean() 等函数将一个值转换为对应的类型。

隐式类型转换是指在运行时自动进行的类型转换,例如在使用 + 运算符时,如果其中一个操作数是字符串,那么另一个操作数也会被转换为字符串。

String()

String() 方法将一个值转换为字符串类型。它可以用于任何数据类型,包括数字、布尔值、对象和数组等。例如:

const num = 123;
const str = String(num);
console.log(typeof num, typeof str, str); // number string 123

const bool = true;
const boolStr = String(bool);
console.log(typeof boolStr, boolStr); // string "true"

const obj = {name: 'Alice', age: 18};
const objStr = String(obj);
console.log(typeof objStr, objStr); // string "[object Object]"

const arr = [1, 2, 3];
const arrStr = String(arr);
console.log(typeof arrStr, arrStr); // string "1,2,3"

  需要注意的是,数组使用 String() 方法时,会将数组转换为逗号分隔的字符串。

// 隐式转换
const result = '123' + 456;
console.log(typeof result); // string

toString()

.toString() 方法将一个值转换为字符串类型。它可以用于任何数据类型,包括数字、布尔值、对象和数组等。例如:

const num = 123;
const str = num.toString();
console.log(typeof str, str); // string "123"

const bool = true;
const boolStr = bool.toString();
console.log(typeof boolStr, boolStr); // string "true"

const obj = {name: 'Alice', age: 18};
const objStr = obj.toString();
console.log(typeof objStr, objStr); // string "[object Object]"

const arr = [1, 2, 3];
const arrStr = arr.toString();
console.log(typeof arrStr, arrStr); // string "1,2,3"

需要注意的是,数组使用 .toString() 方法时,会将数组转换为逗号分隔的字符串。

Number()

将一个字符串类型的数字转为数字类型。它可以用于任何数据类型,包括字符串、布尔值和对象等。例如:

const str = '123';
const num = Number(str);
console.log(typeof num, num); // number 123

const str2 = '456.456';
const num2 = Number(str2);
console.log(typeof num2, num2); // number  456.456

const bool = true;
const boolNum = Number(bool);
console.log(typeof boolNum, boolNum); // number 1

const obj = {name: 'SteveRocket', age: 18};
const objNum = Number(obj);
console.log(typeof objNum, objNum); // number NaN

const str3 = '123.456f'
const num3 = Number(str3)
console.log(typeof num3, num3); // number NaN

需要注意的是,如果转换的值无法转换为数字类型,会返回 NaN

// 隐式转换
console.log(typeof +"123456"); // number

Boolean()

Boolean() 方法将一个值转换为布尔值类型。它可以用于任何数据类型,包括数字、字符串、对象和数组等。例如:

const num = 123;
const bool1 = Boolean(num);
console.log(typeof bool1, bool1); // boolean true

const str = '';
const bool2 = Boolean(str);
console.log(typeof bool2, bool2); // boolean false

const obj = {name: 'SteveRocket', age: 18};
const bool3 = Boolean(obj);
console.log(typeof bool3, bool3); // boolean true

const arr = [];
const bool4 = Boolean(arr);
console.log(typeof bool4, bool4); // boolean true  注意  此处竟然是true,类比Python为false

console.log(Boolean(undefined), Boolean(NaN)); // false false

需要注意的是,空字符串、0、nullundefinedNaN 都会被转换为 false,其他值都会被转换为 true

toJSON()

.toJSON() 方法将一个对象转换为 JSON 字符串。它通常在 JSON.stringify() 方法中使用。例如:

const obj = {name: 'SteveRocket', age: 25};
const jsonStr = JSON.stringify(obj);
console.log(jsonStr, typeof jsonStr);  // {"name":"SteveRocket","age":25} string

const persons = [{name: 'SteveRocket', age: 25},{name: 'Cramer', age: 18}];
const jsonStr2 = JSON.stringify(persons);
console.log(jsonStr2, typeof jsonStr2);  // [{"name":"SteveRocket","age":25},{"name":"Cramer","age":18}] string

const personStr = '[{"name": "SteveRocket", "age": 25},{"name": "Cramer", "age": 18}]';
//使用JSON函数
const personJson2 = JSON.parse(personStr);
console.log(personJson2, typeof personJson2, personJson2[0]);  // [ { name: 'SteveRocket', age: 25 }, { name: 'Cramer', age: 18 } ] object { name: 'SteveRocket', age: 25 }

需要注意的是,如果对象中定义了 .toJSON() 方法,那么在转换为 JSON 字符串时会调用该方法。例如:

const obj2 = {name: 'SteveRocket', age: 25, toJSON(){
    return {name: this.name.toUpperCase()};
    }};
console.log(obj2);  // { name: 'SteveRocket', age: 25, toJSON: [Function: toJSON] }
const jsonStr3 = JSON.stringify(obj2);
console.log(typeof jsonStr3, jsonStr3);  // string {"name":"STEVEROCKET"}

在这个例子中,定义了 .toJSON() 方法,返回一个新的对象,只包含 name 属性的大写形式。

parseInt()

parseInt() 方法将一个字符串转换为整数类型。它的语法如下:

parseInt(string, radix)

其中,string 表示要转换的字符串,radix 表示进制数,可以省略,默认为 10。例如:

const str1 = '123';

const num1 = parseInt(str1);

console.log(typeof num1, num1); // number 123

const str2 = '0x10';

const num2 = parseInt(str2);

console.log(typeof num2, num2); // number 16

const str3 = '1010';

const num3 = parseInt(str3, 2);

console.log(typeof num3, num3); // number 10

需要注意的是,如果字符串无法转换为整数,会返回 NaN

parseFloat()

parseFloat() 方法将一个字符串转换为浮点数类型。它的语法如下:

parseFloat(string)

其中,string 表示要转换的字符串。例如:

const str1 = '3.14';

const num1 = parseFloat(str1);

console.log(typeof num1, num1); // number 3.14

 

const str2 = '1.23e+5';

const num2 = parseFloat(str2);

console.log(typeof num2, num2); // number 123000

需要注意的是,如果字符串无法转换为浮点数,会返回 NaN

9. 隐式类型转换的坑

JavaScript 中的隐式类型转换是一把双刃剑,它可以让代码更加简洁,但也会导致一些奇怪的问题,比如在进行比较运算时,最好使用严格比较运算符。其中最常见的问题就是比较运算符(== 和 !=)的隐式类型转换。

当使用比较运算符进行比较时,如果两个操作数的类型不同,JavaScript 会尝试将它们转换为相同的类型,然后再进行比较。这个过程中会涉及到一些奇怪的规则,例如:

  • 如果其中一个操作数是布尔值,那么将其转换为数字进行比较。

  • 如果其中一个操作数是字符串,那么将另一个操作数转换为字符串进行比较。

  • 如果其中一个操作数是对象,那么将其转换为原始值(例如使用 valueOf() 或 toString() 方法)进行比较。

例如:

console.log(123 == '123'); // true

console.log(0 == false); // true

console.log('' == false); // true

console.log(null == undefined); // true

console.log({} == {}); // false

console.log(true == {}); // false

console.log(true == []); // false

console.log({} == []); // false

这些规则非常复杂,容易出现意想不到的结果。因此,在进行比较运算时,最好使用严格比较运算符(=== 和 !==),它们不会进行隐式类型转换,只有在类型相同的情况下才会返回 true。

例如:

console.log(123 === '123'); // false

console.log(0 === false); // false

console.log('' === false); // false

console.log(null === undefined); // false

console.log({} === {}); // false

10. 相等比较

JavaScript 中有两种比较运算符:相等比较运算符(== 和 !=)和严格比较运算符(===和 !==)。其中,相等比较运算符会进行类型转换,而严格比较运算符不会进行类型转换。在 项目开发中,务必使用 === 三个等于号来比较对象,或者自定义方法来比较,不要使用 ==

相等比较运算符会尝试将两个操作数转换为相同的类型,然后再进行比较。这个过程中会涉及到一些奇怪的规则,例如:

  • 如果其中一个操作数是布尔值,那么将其转换为数字进行比较。

  • 如果其中一个操作数是字符串,那么将另一个操作数转换为字符串进行比较。

  • 如果其中一个操作数是对象,那么将其转换为原始值(例如使用 valueOf() 或 toString() 方法)进行比较。

严格比较运算符不会进行类型转换,只有在类型相同的情况下才会返回 true。

例如:

console.log(123 == '123'); // true

console.log(123 === '123'); // false

在进行比较运算时,最好使用严格比较运算符,避免出现意想不到的结果。

推荐如下比较方法:

var number1 = 31243; var str1 = '31243';
console.log(String(number1) === String(str1)); // true

更多精彩,关注我公号 ,一起学习、成长 图片.png

Node.js系列文章推荐阅读: