整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

如何避免JavaScript类型转换

本已经过原作者 Viduni Wickramarachchi 授权翻译。

你是否经历过JavaScript中的某些值比较没有得到预期结果的情况?

看下面的情况:

即使[]==0结果为真,if[]条件也没有根据结果执行。有没有想过为什么会这样?

本文主要说明这些值比较的工作原理以及影响它们的因素。在深入解释之前,大家要熟悉一个概念:类型转换

什么是 JavaScript 类型转换?

这也称为类型强制。对于不熟悉此概念的人来说,它只是将值从一种数据类型自动转换为另一种数据类型。

看个例子,大家会更清楚明白。

在此示例中,定义的两个变量具有两种类型;字符串和数字。但是,当我们使用 ==(非严格比较)进行比较时,结果为true。原因是当我们使用==比较这两个时,JavaScript 会自动尝试将String类型转换为Number类型以产生结果。这是一种强制转换。

JavaScript中有多种强制类型。

  • Number conversions
  • String conversions
  • Boolean conversions
  • 对象的类型转换

类型强制转换都是好的吗?

在上述情况下,类型转换没有害处。但是,在许多情况下,类型强制会导致问题。

我们看下面例子。

在这里,JavaScript已将Number类型转换为String。这与相等比较中发生的情况相反。我们预期的结果是450。但是,我们得到了String输出。

现在,我们对类型转换以及为什么要避免使用类型转换有了清晰的了解,让我们看看如何避免类型转换。这是本文最重要的部分。因此,请坐下来,喝咖啡并集中精力

如何避免 JavaScript 类型转换

1. 对数学运算使用显式转换

如果你需要对用户输入或任何其他值使用数学运算,则在执行该运算之前,自己进行一次显式转换会更安全。这样,可以避免任何意外行为。

2. 使用模板字面值连接字符串,而不是+

如果需要连接两个数字,则使用模板文字会更安全。特别是不确定值的类型。

也可以使用显式转换来导出相同的结果。

3.当比较值时,使用严格的比较(===)

前面我们看到,当使用==时,JavaScript 会执行隐式类型转换,这会导致不一致的结果。因此,在我们的生产代码中使用它是不安全的。

为了得出预期的结果,应该始终使用===进行比较。三等号隐含地表示:

我可以同时了解变量的值和类型

因此,如果将数字和字符串与值进行比较,结果将是false,因为它也会考虑变量的类型。

这是获得预期一致结果的更安全的方法。

在JavaScript中,数据类型有两种变体。

  • 原始值(字符串、数字等)
  • 非原始值(数组、对象)

到目前为止,我们已经讨论了原始数据类型的类型转换。我提供的第一个示例涉及非原始数据类型,例如数组。

所有非原始数据类型都有一个名为.toPrimitive()的内置函数。比较非原始值和原始值时,此函数会自动将非原始类型转换为原始类型。在我们看过的第一个示例中,当使用此函数进行非严格比较时,空数组将转换为空字符串。确切地说,用于执行此转换的确切函数是toString()。因此,空数组(将转换为空字符串)等于0

正如我们前面所看到的,当在if条件中检查空数组时,将执行条件中的行。但是,如果空数组隐式转换为0怎么办?

这是在单独的JavaScript条件下进行的: 真值和虚值 。除了true以外,JavaScript 将大部分有值的视为真值,除了少数值。例如,0-0""被视为虚值。由于空数组不被认为是虚值,当在条件中检查它时,它将作为真值执行。(这里不会发生类型转换,空数组保留为数组,这是类型转换不一致的另一个例子。)

总结

JavaScript作为一种松散类型语言,执行隐式类型转换。这会导致不一致和意想不到的结果。因此,我们应该在任何时候都避免这种类型转换。如果不确定值的类型,可以使用typeof检查。检查类型可以让我们更好地理解应该如何进行转换。

~完,我是刷碗智,我要去刷碗了,骨的白~


作者:Viduni Wickramarachchi 译者:前端小智 来源:stackabuse

原文:https://blog.bitc.io/how-to-avoid-javascript-type-conversions-29e1258f37d8

tml+css基础一:html简介和发展史

HTML全称(hypertext markup language)译为超文本标记语言,其译文代表了HTML的含义,它和其他编程语言不同的是,HTML不是一门真正意义上编程语言,而是一种标记语言,通过带有尖角号的标签对文本进行标记,从而实现网页的结构搭建。

1.2、HTML发展史

HTML创始人(蒂姆·伯纳斯-李)蒂姆·伯纳斯-李除了是HTML的创始人,还是w3c组织的主席。

1、HTML1.0 (1991年12月)

1991年万维网(www)在互联网上首次露面,也随之引起了巨大的轰动。

1989年,伯纳斯-李写了一份备忘录,提出建立一个基于互联网的超文本系统。同年和另外一个工程师一起进行联合资金申请,但是这个项目并没有通过。

1991年底的时候,伯纳斯-李公开了一份“HTML Tag”的文档,里面描述了组成HTML初始版本的18个元素

2、HTML2.0(1995年11月)

HTML 2.0是HTML语言的扩展。    

与原始版本的HTML不同,HTML 2.0被创建为Web标准,规定了常见的网页结构

3、HTML3.2(1996年1月)

惨淡的"第一次浏览器大战时期(Netspace Vs IE)",两大巨头不断推出重大举措试图控制整个领域。       

网页开发者是这场战争中的焦点。商业战争就像军备竞赛,各家公司为了保持领先,招兵买马。各家都有各家的规则。         

那时候,你不得不写两份不同的网页,一个用于网景的浏览器,另一个用于微软的浏览器

4、HTML4(1997年12月)

浏览器大战接近尾声,W3C(世界万维网联盟)成立,他们打算通过制定统一的HTML标准,使整个产业能有序的发展。            

他们计划用两种语言分离出HTML的表达式(HTML 4.0)和结构(CSS),并且说服浏览器厂商接受这些标准

这次发布提供了规范的三种变体:

Strict,严格版本;

Transitional,过渡版本;

Frameset,iframe框架集;

HTML4.0 采纳了许多浏览器特定的元素类型及属性,但是同时也把 Netscape 的视觉化标记标记为过时的寻求淘汰; 赞成使用样式表; 同时在1998年4月对HTML4.0进行了微小的修订,没有增加版本号HTML5.0

5、HTML4.01(1999年12月)

像 HTML4.0 一样提供了三种变体,并且他的最终错误修订版在2001年的5月12日发布

6、XHTML 1.0(2000年1月)

各大浏览器厂商纷纷接受W3C标准的时候,新技术出现了。             

HTML和另一种语言XML融合,XHTML(可拓展的超文本标记语言)就此诞生。           

它继承了HTML的通用型和浏览器的兼容性,继承了XML的严密性和可拓展性

7、HTML5(2014 年 10 月)

HTML5是HTML最新的修订版本,由W3C制定,目标是取代1999年所制定的HTML 4.01和XHTML 1.0标准

我们现在使用的是html5版本,因为由于新兴框架的出现和浏览器兼容性的提升,让我们选择了html5。

:基本概念

this字面意思是当前,当前执行代码的环境对象或者是上下文。代表着当前方法执行的环境上下文,那么何为环境上下文,通俗的说,谁调用了函数,谁就是这个函数的环境上下文。

在js中,this只有两种指向,一种是指向当前的封闭作用域,或者是指向当前作用域的外层,this的最顶层就是window对象

关于this必须要了解的是严格模式,严格模式是js里面的一个子集,是具有限制性JavaScript变体,严格模式也是js的一种,但是加了一些限制。

比如:

  • 在严格模式下通过抛出错误来消除了一些原有的静默错误(静默错误:语法有错误但是js并没有提示,默认允许这个操作)。比如要取一个函数的传入参数,在非严格模式下,可以直接拿到它的grument,但在严格模式下会抛出一个错误。
  • 严格模式修复了一些导致JavaScript引擎难以执行优化的缺陷
  • 禁用了在ECMAScript的未来版本中可能会定义的一些语法

进入"严格模式"的标志:"use strict";

// 为整个脚本开启严格模式 
"use strict";
var v = "Hi! I'm a strict mode script!";
​
// 为函数开启严格模式 
function strict() {
 'use strict';
 function nested() { 
 return "And so am I!"; 
 }
 return "Hi! I'm a strict mode function! " + nested();
}

2:全局环境

在全局环境下,无论是否在严格模式下,在全局执行环境下(任何函数体外部)this指向全局对象。也就是说在全局执行环境,这个this永远指向全局对象,这个全局对象在浏览器中就是window。

//浏览器环境
var name = 'Eric';
console.log(window.name === this.name); /* true */
console.log(window === this); /* true */

3:函数体内部

在函数体内部,this的值取决于函数被调用的方式。函数被调用的方式有很多种:

简单调用,也就是说没有添加任何额外的操作,没有添加一个this的绑定或者是改变。

简单调用分为严格模式与非严格模式。

  • 在非严格模式下,this默认指向全局对象。
// 浏览器环境
function simple(){
 return this;
}
console.log(simple() === window);
// true
  • 在严格模式下,保持进入执行环境时的值,没有指定时默认undefined。
// 浏览器环境
function simple2(){
 "use strict";
 return this;
}
simple2() === undefined;
// true 
window.simple2() === window;
// true 

this传递,在js中this绑定有两种:

  • 一种是call/apply,可以看作是一种,它们都是一个绑定this的立即执行的一个方法,绑定之后会立即执行这个函数,两者的区别在于传递参数的不同,一个是传一个参数,一个是传一堆参数;call/apply实际上是绑定值的是一个对象,存在一个ToObject过程。call/apply是一个立即执行的绑定this的一个操作。
// 浏览器环境 
var object = {
 name: 'Eric'
};
var name = 'Iven';
function getName(arg) {
 return this.name;
}
​
getName(); /* Iven */
getName.call(object); /* Eric */
getName.apply(object); /* Eric */
  • 另一种是bind,与上面不同的是bind不会立即执行,它只是实现一个绑定的过程,返回的是一个柯里化的函数,这个柯里化的函数就是call/apply。bind只能被绑定一次。
name = 'Davy';
function bindThis(){
 return this.name;
}
var getName1 = bindThis.bind({ name: "Eric" });
console.log(getName1()); /* Eric */
​
var getName2 = getName1.bind({ name: "Iven" });
console.log(getName2()); /* Eric */

箭头函数在执行的时候会形成一个封闭的作用域,this与封闭作用域的this保持一致,call/apply/bind都将会被忽略。

// 浏览器环境 
var globalThis = this;
var arrowsFunction = () => this;
console.log(arrowsFunction() === globalObject); /* true */

作为对象的方法被调用(有一个靠近原则):在对象里面定义了一个函数,然后通过对象去调用这个函数。

// 浏览器环境 
var object = {
 name: 'Eric',
​
 getName: function() {
 return this.name;
 }
};
console.log(object.getName()); /* Eric */
​
​
function getName2() {
 return this.name;
}
object.getName = getName2;
console.log(object.getName()); /* Eric */
​
​
object.object = {
 getName: getName2,
 name: 'Iven'
};
console.log(object.object.getName()); /* Iven */

4:全局函数

  • setTimeout
  • setInterval
  • alert

setInterval()方法用于在指定的毫秒数后调用函数或计算表达式。

语法:setTimeout(code,millisec),参数code必需,要调用的函数后执行的JavaScript代码串;millisec必需,在执行代码前等待的毫秒数。

注意:setTimeout()只执行code一次,如果需要多次调用,请使用setInterval()或者让code自身再次调用setTimeout(),也就是利用递归。

setInterval()方法可按照指定的周期来调用函数或计算表达式。它会不停地调用函数,指导clearInterval()被调用或者窗口被关闭。由setInterval()返回的ID值可以用作clearInterval()方法的参数。