【译】我最喜欢的Javascript的窍门和小技巧

468 阅读7分钟

掘金翻译计划
原文地址:文章链接

动机

大多数编程语言都足够开放,让编程者们有多种方式去处理类似的结果。Javascript也不例外。使用Javascript,我们常常用多种方式去达到相似的结果,有时候会造成混淆。 一些用法比其他替代方法要好,因此,这些是我最喜欢的。我打算把它们在文章中列举出来,我敢肯定,你在列表中也会找到很多。

1.忘掉字符串拼接,使用模板字符串语法(文字)

利用"+"运算符拼接字符串构建有意义的字符是很老派的做法。因此,在拼接变量(或表达式)的时候用拼接字符串可能会不尽如人意和导致bug。

  let name = 'Charlse';
  let place = 'India';
  let isPrime = bit => {
    return (bit === 'P' ? 'Prime' : 'Nom-Prime');
  }

  // string concatenation using + operator
  let messageConcat = 'Mr. ' + name + ' is from ' + place + '. He is a' + ' ' + isPrime('P') + ' member.'

模版文字(或模版字符串)允许嵌入表达式。他具有特殊的语法,字符串被反引号(``)包裹,模版字符串可以包含动态值的占位符。这些以美元符号和大括号($ {expression})标记。 这是一个展示它的例子。

  let name = 'Charlse';
  let place = 'India';
  let isPrime = bit => {
    return (bit === 'P' ? 'Prime' : 'Nom-Prime');
  }

  // using template string
  let messageTemplateStr = `Mr. ${name} is from ${place}. He is a ${isPrime('P')} member.`
  console.log(messageTemplateStr);

2.是否为整型(isInteger)

有特别简单明了的方法知道值是否为整型。Number的API提供了一个叫isInteger()的方法实现这个目的。它特别实用值得关注。

  let mynum = 123;
  let mynumStr = "123";

  console.log(`${mynum} is a number?`, Number.isInteger(mynum));
  console.log(`${mynumStr} is a number?`, 	  
  Number.isInteger(mynumStr));

Output: alt

3.数字类型的值

你是否曾经注意到?即使输入框是数字类型,event.target.value 总是返回字符串类型的值。 是的,看下面的例子。我们有个简单的数值类型的文本框。意味着只接受数字类型的值。它具有事件处理程序去处理按键事件。

	<input type='number' onkeyup="trackChange(event)" />

在事件处理程序的方法中我们通过 event.target.value 获取值。但是总是返回字符串类型的值。把它解析成整数又是一个额外的难题。如果文本框接收浮点数类型的数(例如:16.65)?然后用 parseFloat() 转换?哈,各种困惑和多余的工作啊!

	function trackChange(event) {
   	let value = event.target.value;
  	console.log(`is ${value} a number?`, Number.isInteger(value));
}

使用 event.target.valueAsNumber 作为替代,它能返回数字类型的值。

	let valueAsNumber = event.target.valueAsNumber;
	console.log(`is ${value} a number?`, 
    Number.isInteger(valueAsNumber));

alt

4.简短语法利用And符

让我们考虑下我们有一个布尔值和一个函数的情况。

	let isPrime = true;
    const startWatching = () => {
        console.log('Started Watching!');
    }

有很多的代码去检查布尔值的条件和调用函数。

	if (isPrime) {
      startWatching();
  }

要不用下短语法的AND(&&)操作符?对啦,完全避免if语法,很酷是吗?

	isPrime && startWatching();

5.默认值和或

如何你曾经给变量设置过默认值,你可以用OR(||)或运算符轻松实现。

	let person = {name: 'Jack'};
	let age = person.age || 35; // sets the value 35 if age is 		undefined
	console.log(`Age of ${person.name} is ${age}`);

6.随机数Randoms

通常来说随机数或者从数组中得到随机项是非常实用的方法。我已经看到在我很多项目中多次出现。 从数组中获取随机项

	let planets = ['Mercury ', 'Mars', 'Venus', 'Earth', 'Neptune', 'Uranus', 'Saturn', 'Jupiter'];
	let randomPlanet = planets[Math.floor(Math.random() * planets.length)];			
	console.log('Random Planet', randomPlanet);

通过指定最小值和最大值,从一个范围生成一个随机数。

	let getRandom = (min, max) => {
     return Math.round(Math.random() * (max - min) + min);
 }
 	console.log('Get random', getRandom(0, 10));

7.函数默认值

在JavaScript中,函数参数(或参数)就像该函数的局部变量。调用这些函数时,你可能传或不传这些参数值。如果你没传这些参数值,很有可能会导致 undefined 或者不必要的副作用。 有个在定义函数参数时将默认值传递给函数的简单方法,这有个例子,我们在 greetings 函数中 给 message 参数传递默认值 Hello

	let greetings = (name, message='Hello,') => {
    	return `${message} ${name}`;
	}

	console.log(greetings('Jack'));
	console.log(greetings('Jack', 'Hola!'));

8.必需的功能参数

扩展默认参数方法,我们标记一个参数为必传,首先定义一个方法抛出错误信息。

  let isRequired = () => {
      throw new Error('This is a mandatory parameter.');
  }

然后将该函数当作所需参数的默认值,记住,当你的参数传了值的时候,默认值是会被忽略的,但是当参数的值未被定义时默认值才会被考虑。

	let greetings = (name=isRequired(), message='Hello,') => {
    	return `${message} ${name}`;
	}
	console.log(greetings());

在上面的代码中,name将未定义,这将尝试为其设置默认值,即isRequired()函数。它会抛出一个错误, alt

9.逗号运算符

我很惊讶于当我意识到逗号运算符是一个单独的运算符,我之前从没注意到,我已经在代码中是用来很多,但是从来没有意识到它的真实存在。

在Javascript中,逗号运算符(,)用来评估它从左至右每个操作数,并且返回最后一个操作数的值。

    let count = 1;
    let ret = (count++, count);
    console.log(ret);

在上面的例子中,变量ret的值将会是2,同样的,下面这段代码的输出将32的值记录在控制台。

    let val = (12, 32);
    console.log(val);

我们在哪里用到它?猜一猜?逗号运算符最常用的用法就在for循环中提供多个参数。

	for (var i = 0, j = 50; i <= 50; i++, j--)

10.合并多个对象

你可能需要将两个对象合并在一起,创建一个更好的信息对象来使用。你可以使用扩展运算符...(对,三个点) 分别考虑emp和obj两个对象,

  let emp = {
   'id': 'E_01',
   'name': 'Jack',
   'age': 32,
   'addr': 'India'
  };

  let job = {
   'title': 'Software Dev',
    'location': 'Paris'
  };

用展开运算符合并它们,

	let merged = {...emp, ...job};
  console.log('Spread merged', merged);

还有其他对方式去合并它们,使用Object.assign(),你可以像这样做,

	 console.log('Object assign', Object.assign({}, emp, job));

输出: alt 注意:展开运算符和 Object.assign 都是浅合并,在浅合并中,前一个对象的值会被后一个对象的相同属性覆盖。 如果需要深合并,请用类似 lodash 的 ._merge方法。

11.解构

分解数组元素和对象属性的方法被叫做解构,让我们来看看一些例子。

数组

	let emojis = ['🔥', '⏲️', '🏆', '🍉'];

解构,我们使用接下来的语法,

	let [fire, clock, , watermelon] = emojis;

这和做let fire = emojis[0];是一样的,但是更灵活,你有注意过吗?我忽略了奖杯表情,中间用了一个空格。我们将会输出什么?

	console.log(fire, clock, watermelon);

输出: alt 让我也来介绍下剩余运算符。如果你想像这样解构数组,你想要分配一个或多个项分配给变量,然后把剩下的放到另一个数组,你可以像下面所示使用 ...rest

 	let [fruit, ...rest] = emojis;
	console.log(rest);

输出: alt

对象

像数组一样,我们也可以解构对象。

    let shape = {
      name: 'rect',
      sides: 4,
      height: 300,
      width: 500
    };

像这样解构,我们在一组变量中得到了 name,sides和剩余其他对象。

	let {name, sides, ...restObj} = shape;
    console.log(name, sides);
    console.log(restObj);

输出: alt 了解更多这个主题点击这里

12.交换变量

用我们刚刚学过的析构的概念,这一定非常简单。

   let fire = '🔥';
   let fruit = '🍉';
   [fruit, fire] = [fire, fruit];
   console.log(fire, fruit);

13.isArray

    let emojis = ['🔥', '⏲️', '🏆', '🍉'];
    console.log(Array.isArray(emojis));

    let obj = {};
    console.log(Array.isArray(obj));

14. undefined vs null

undefined 是指没有给变量定义值,但是已经声明了。 null 本身是一个空且不存在的值,必须显示地将其分配给变量。

	undefined === null // false

了解更多这个主题点击这里

15. 获取查询参数

window.location 对象有一大串实用的方法和属性。我们可以通过这些属性和方法从浏览器链接获取协议,主机,端口号,域名等相关信息。
其中我发现一个很实用的属性是,

	window.location.search

search 属性会从本地Url地址中返回查询的字符串。这里有个例子url : https://tapasadhiary.com?project=js 这个location.search 将返回 ?project=js
我们能使用其他有用接口叫做,URLSearchParams 跟之前的 location.search 一样获取到查询参数

	let project = new URLSearchParams(location.search).get('project');

输出:js
了解更多这个主题点击这里