夕阳依旧 發表於 2019-5-9 16:45:00

新手怎么学JS?JavaScript基础入门

<h1 id="javascript入门---01">新手应该怎么学习JS?JavaScript入门 - 01</h1>
<h2 id="准备工作">准备工作</h2>
<p>在正式的学习<code>JavaScript</code>之前,我们先来学习一些<code>小工具</code>,帮助我们更好的学习和理解后面的内容。</p>
<h3 id="js代码位置">js代码位置</h3>
<p>首先是如何编写<code>JavaScript</code>代码,说到这,我们首先要来说明一个需要新人们关注的点,因为我们的<code>js</code>是一门<code>跨平台</code>的语言,所以说,我们的代码可以运行在不同的<code>平台</code>之上。这也就导致了可能相同的代码放在不同的平台运行就会有所出入。</p>
<blockquote>
<p>这里面说的平台其实被称之为<code>宿主环境</code>。</p>
</blockquote>
<p>同时,代码在不同的平台上的运行方式也有所不同。</p>
<p>如果运行在<code>服务端</code>,那么更多的时候我们需要通过命令行的形式去运行,而如果是代码运行在<code>客户端</code>,则需要通过启动<code>浏览器</code>来运行代码。</p>
<p>我们在学习的初期建议是在<code>浏览器</code>中运行代码,减少学习成本。</p>
<p>首先,我们的<code>js</code>代码可以写在<code>script</code>标签内部并且将<code>script</code>标签放在网页的任何位置。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;!DOCTYPE html&gt;
&lt;html lang="zh"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="ie=edge"&gt;
    &lt;title&gt;&lt;/title&gt;
    &lt;script&gt;
      // js code ...
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;script&gt;
      // js code ...
    &lt;/script&gt;
&lt;/body&gt;
&lt;script&gt;
    // js code ...
&lt;/script&gt;
&lt;/html&gt;
</pre>
</div>
<p>  </p>
<p>在上面的代码中,我们把包含有<code>js</code>代码的<code>script</code>标签放在了<code>head</code>标签、<code>body</code>标签、和<code>body</code>标签之后的位置。从语法的层面来说,上面的这几种写法都是正确的。但是在本教程中较为推荐的写法是将<code>scirpt</code>标签放在<code>body</code>标签的闭合标签的后面。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;!DOCTYPE html&gt;
&lt;html lang="zh"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="ie=edge"&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;/body&gt;
&lt;script&gt;
    // js code ...
&lt;/script&gt;
&lt;/html&gt;
</pre>
</div>
<p>  </p>
<blockquote>
<p>推荐的原因,是因为<code>js</code>代码经常需要操作<code>html</code>标签,而放在后面可以等到<code>html</code>标签加载完毕之后再来执行<code>js</code>代码。避免因为<code>html</code>标签未加载而导致的报错。</p>
</blockquote>
<p>而另外一种写法是将<code>js</code>代码完全的写在一个后缀名为<code>.js</code>的文件中。在需要的<code>html</code>文件中通过<code>script</code>标签引入。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;!DOCTYPE html&gt;
&lt;html lang="zh"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="ie=edge"&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
   
&lt;/body&gt;
// 通过src属性与script标签配合引入外部的js文件
&lt;script src="01.js"&gt;&lt;/script&gt;
&lt;/html&gt;
</pre>
</div>
<p>  </p>
<h3 id="js语句">js语句</h3>
<p><code>js</code>当中的语句表示<code>js</code>向宿主环境发送的命令。</p>
<p>例如下面的语句是向页面中输出计算<code>10 + 2</code>的结果。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">document.write(10+2);
</pre>
</div>
<p>  </p>
<p>在每一条语句的后面都带有一个分号,表示语句结束。</p>
<p>当然<code>js</code>允许我们将分号省略掉,但是无论是从代码的维护成本还是其他因素考虑,都不建议将每条语句后面的分号省略掉。</p>
<p>需要注意的是,如果分号前面的语句为空,则没有意义。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;"> ; ; ;
</pre>
</div>
<p>  </p>
<p>类似上面的语句代码是没有意义的。</p>
<h3 id="注释">注释</h3>
<p><code>注释</code>是任何编程语言当中必不可少的一环。通过注释,可以让我们开发过的代码具有更好的可读性,也能变相的提升后期代码的维护和升级速度。</p>
<p>一般情况下,注释的内容可以包含很多,例如<code>参数信息</code>,<code>代码功能</code>、<code>使用方式</code>等等。</p>
<p>在<code>js</code>中,<code>注释</code>分为两种,一种是<code>单行注释</code>,一种是<code>多行注释</code>。</p>
<p><code>单行注释</code>通过<code>//</code>表示,一般写在语句的后面或者语句的上方。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">// 这里是代码注释
</pre>
</div>
<p>  </p>
<p><code>多行注释</code>通过<code>/**/</code>的形式来创建,一般写在代码的上方。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">/*
这里是多行注释...
*/
</pre>
</div>
<p>  </p>
<p>无论你是一个<code>js</code>新人,还是一个<code>成熟的老程序员</code>,合理的应用<code>注释</code>都是一个非常好的习惯。</p>
<h3 id="直接量">直接量</h3>
<p>在<code>js</code>中,直接使用的量,我们称之为叫做<code>直接量</code>。</p>
<p>例如,在代码中,我们要使用<code>10</code>,那么这个<code>10</code>就是一个<code>直接量</code>。</p>
<h3 id="表达式">表达式</h3>
<p>一般情况下,<code>表达式</code>需要得到一个结果。</p>
<p>例如<code>10+2</code>就是一个表达式,我们在创建这个表达式的时候,就希望得到<code>10+2</code>的结果。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">document.write(10+2);// 通过document.write()方法将10+2这个表达式的结果输出到网页当中
</pre>
</div>
<p>  </p>
<h3 id="输出方式">输出方式</h3>
<p>我们在编写<code>js</code>代码的时候,经常需要得到计算的值,用以判断得到的值与我们预期的值是否相符,所以我们需要了解下面的基本的输出方式。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">// console.log() 将内容输出到浏览器的控制台
console.log(10+2);
// document.write() 将内容输出到网页当中
document.write(10+2);
</pre>
</div>
<p>  </p>
<blockquote>
<p>通常情况下我们通过<code>console.log()</code>这种形式输出代码我们称之为<code>代码打印</code>。</p>
</blockquote>
<h3 id="弹窗">弹窗</h3>
<p>在<code>js</code>中,如果你的代码运行环境是在<code>浏览器</code>当中,那么就可以使用<code>浏览器</code>给我们提供的弹窗。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">alert(10+2);
confirm(10+2);
prompt(10+2);
</pre>
</div>
<p>  </p>
<blockquote>
<p>上述的三个弹窗只能够在<strong>运行环境为浏览器的情况下使用。</strong></p>
</blockquote>
<h2 id="变量">变量</h2>
<p>我们上面说到了<code>表达式</code>,通过<code>表达式</code>能够得到计算的结果,但是如果我们计算的逻辑较为复杂,那么如果单纯的依赖表达式将会变得不那么方便。</p>
<p>这个时候,就可以使用<code>变量</code>。</p>
<p>什么是<code>变量</code>呢?</p>
<p>我们可以把<code>变量</code>理解为是一个<code>代名词</code>或者说叫做<code>临时的容器</code>。</p>
<p>我们可以把一个具体的值存入到变量中。那么此时这个变量就代表着我们这个具体的值。我们如果想要重新的使用这个值,不再需要重新的计算或者其他操作,直接使用变量就可以得到之前存储的这个值。</p>
<p>而想要创建一个变量(也可以说是<code>声明</code>一个变量),需要通过<code>var</code>关键字(<code>es6</code>中通过<code>let</code>声明)。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var val = 10 + 2;</pre>
</div>
<p>在上面的代码中,我们创建了一个变量<code>val</code>,并且使用这个变量<code>val</code>存储了表达式<code>10+2</code>的计算结果。那么如果想要第二次使用<code>10+2</code>的结果,可以直接使用变量<code>val</code>即可。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">console.log(val);// 通过console.log() 输出val,此时就可以在控制台看到10+2的结果</pre>
</div>
<p>在我们使用<code>变量</code>的时候,还有一点需要理解,<code>变量</code>之所以叫变量,是因为<code>变量</code>随时可以根据我们的需要更改其中存储的值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = 10;
a = 20; // 当我们重新的向变量中存储数据的时候,不需要再加var
console.log(a); // 此时再打印a结果就为20</pre>
</div>
<p>需要注意的是,上面我们将变量<code>a</code>内存储的数据由<code>10</code>变成了<code>20</code>,在重新存储的过程中,我们并没有使用<code>var</code>,那么上面的代码就相当于我们将<code>20</code>的值存储到之前创建的变量<code>a</code>中。</p>
<p>而如果在重新的存储的过程中使用了<code>var</code>,如同下面的案例:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = 10; // 第一次声明变量a
var a = 20; // 再一次通过var声明变量a,并且使用了var
consoloe.log(a);
</pre>
</div>
<p> </p>
<p>需要注意的是,虽然最后的结果和上面的打印结果相同,但是变量<code>a</code>本质上已经发生了变化。</p>
<p><strong>如果在重新存储数据的过程中,没有在变量名前面加var,那么相当于是更改变量a中存储的值,而如果前面加了var,则相当于重新的创建了一个变量a,并且存储了20这个数据</strong>。</p>
<p>如果采用下面的这种写法,那么重新创建的变量将会无效:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var x = 1;
var x;
x // 1
</pre>
</div>
<p>  </p>
<p><strong>变量提升:</strong></p>
<p><code>JavaScript</code>&nbsp;引擎的工作方式是,<strong>先解析代码,获取所有被声明的变量,然后再一行一行地运行。</strong>这造成的结果,就是<code>所有的变量的声明语句,都会被提升到代码的头部</code>,这就叫做<strong>变量提升(hoisting)</strong>。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">console.log(a);
var a = 1;
</pre>
</div>
<p>  </p>
<p>上面代码首先使用<code>console.log</code>方法,在控制台(console)显示变量<code>a</code>的值。这时变量<code>a</code>还没有声明和赋值,所以这是一种错误的做法,但是实际上不会报错。因为存在变量提升,真正运行的是下面的代码。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a;
console.log(a);
a = 1;
</pre>
</div>
<p>  </p>
<p>最后的结果是显示<code>undefined</code>,表示变量<code>a</code>已声明,但还未赋值。</p>
<h2 id="标识符">标识符</h2>
<p>标识符(identifier)指的是用来识别各种值的合法名称。最常见的标识符就是变量名,以及后面要提到的函数名。JavaScript 语言的标识符对大小写敏感,所以<code>a</code>和<code>A</code>是两个不同的标识符。</p>
<p>标识符有一套命名规则,不符合规则的就是非法标识符。JavaScript 引擎遇到非法标识符,就会报错。</p>
<p>简单说,标识符命名规则如下。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号($)和下划线(_)。
第二个字符及后面的字符,除了 Unicode 字母、美元符号和下划线,还可以用数字0-9。
</pre>
</div>
<p>  </p>
<p>下面这些都是合法的标识符。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">arg0
_tmp
$elem
π
</pre>
</div>
<p>  </p>
<p>下面则是一些不合法的标识符:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">1a// 第一个字符不能是数字
23// 同上
***// 标识符不能包含星号
a+b// 标识符不能包含加号
-d// 标识符不能包含减号或连词线
</pre>
</div>
<p>  </p>
<p>需要注意的是,在<code>js</code>当中,中文也是合法的标识符,但是并不推荐使用。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">JavaScript 有一些保留字,不能用作标识符:arguments、break、case、catch、class、const、continue、debugger、default、delete、do、else、enum、eval、export、extends、false、finally、for、function、if、implements、import、in、instanceof、interface、let、new、null、package、private、protected、public、return、static、super、switch、this、throw、true、try、typeof、var、void、while、with、yield。
</pre>
</div>
<p>  </p>
<h2 id="数据类型">数据类型</h2>
<p><code>变量</code>用来临时存储数据(如果想要永久的存储数据,需要通过数据库)。而在任何一门编程语言当中,数据都是分为不同类型的。就如同人类也分为男人和女人一样。</p>
<p>下面就来说一下在<code>JavaScript</code>中数据的不同类型。</p>
<p>在<code>js</code>当中数据类型分为两类,一类是<code>原始类型</code>,一类是<code>引用数据类型</code>。<code>原始类型</code>又称之为<code>基础数据类型</code>,<code>引用类型</code>也称之为<code>对象类型</code>。</p>
<p><code>原始类型</code>的数据包含有下面几个:</p>
<ul>
<li>Boolean</li>
<li>Null</li>
<li>Undefined</li>
<li>Number</li>
<li>String</li>
<li>Symbol(ES6中新增加的内容)</li>
</ul>
<p><code>引用类型</code>的数据包含有下面几个:</p>
<ul>
<li>Object</li>
<li>Array</li>
<li>Function</li>
</ul>
<blockquote>
<p>在<code>js</code>当中,<code>引用类型</code>也包括<code>Date</code>、<code>Math</code>和<code>RegExp</code>等内容。</p>
</blockquote>
<blockquote>
<p>需要注意的是,<code>JS</code>当中的原始值并不能够更改,也就意味着一旦一个原始值创建成功。那么将不能够进行第二次的值得修改,除非重新创建一个数据。</p>
</blockquote>
<h2 id="boolean">Boolean</h2>
<blockquote>
<p>In computer science, a&nbsp;<strong>Boolean</strong>&nbsp;is a logical data type that can have only the values&nbsp;<code>true</code>&nbsp;or&nbsp;<code>false</code>. For example, in JavaScript, Boolean conditionals are often used to decide which sections of code to execute (such as in&nbsp;if statements) or repeat (such as in&nbsp;for loops).</p>
</blockquote>
<p>在<code>MDN</code>中,对于<code>JavaScript</code>中的<code>布尔值(Boolean)</code>有上面一段描述,翻译过来的意思大致如下:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">在计算机科学中,布尔值是一种逻辑数据类型,其值只能为真或假。例如,在JavaScript中,布尔条件
常用于决定执行哪一部分代码(例如在if语句中)或重复(例如在For循环中)。
</pre>
</div>
<p>  </p>
<p><code>布尔值</code>包含有两个值<code>true</code>和<code>false</code>。其中<code>true</code>表示<code>真</code>,<code>false</code>表示<code>假</code>。</p>
<p>例如我们判断一个条件,如果这个条件满足,那么对应着布尔值<code>true</code>,如果这个条件不满足,那么就对应着布尔值<code>false</code>。</p>
<p>下列运算符会返回布尔值:</p>
<ul>
<li>前置逻辑运算符:&nbsp;<code>!</code>&nbsp;(Not)</li>
<li>相等运算符:<code>===</code>,<code>!==</code>,<code>==</code>,<code>!=</code></li>
<li>比较运算符:<code>&gt;</code>,<code>&gt;=</code>,<code>&lt;</code>,<code>&lt;=</code></li>
</ul>
<p>如果 JavaScript 预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为<code>false</code>,其他值都视为<code>true</code>。</p>
<ul>
<li><code>undefined</code></li>
<li><code>null</code></li>
<li><code>false</code></li>
<li><code>0</code></li>
<li><code>NaN</code></li>
<li><code>""</code>或<code>''</code>(空字符串)</li>
</ul>
<h2 id="null">Null</h2>
<blockquote>
<p>In computer science, a&nbsp;<strong>null</strong>&nbsp;value represents a reference that points, generally intentionally, to a nonexistent or invalid&nbsp;object&nbsp;or address. The meaning of a null reference varies among language implementations.</p>
<p>In&nbsp;JavaScript, null is one of the&nbsp;primitive values.</p>
</blockquote>
<p>译文:</p>
<blockquote>
<p>在计算机科学中,空值表示一个引用,该引用通常有意指向不存在或无效的对象或地址。空引用的含义因语言实现而异。</p>
<p>在JavaScript中,null是一个基本值(原始数据)。</p>
</blockquote>
<p><code>Null</code>类型里面只有一个值,就是<code>null</code>。<br>关于<code>null</code>,你可以把它理解为<code>无</code>,它表示一个空值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = null;
</pre>
</div>
<p>  </p>
<p>例如上面的代码当中,你可以理解为此事的变量a表示的值为空。</p>
<blockquote>
<p>当我们在一些需要传递值的地方,如果我们没有值进行传递,那么就可以传递一个<code>null</code>,表示传递的值为空。</p>
</blockquote>
<h2 id="undefined">undefined</h2>
<p><code>Undefined</code>类型当中只有一个值就是<code>undefined</code>。</p>
<p>在代码的编写过程中,一个没有被赋值的变量的类型就是<code>undefined</code>。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a;
console.log(a); // 会在浏览器的控制台中输出undefined
</pre>
</div>
<p>  </p>
<p>如果一个变量声明但是没有被赋值,我们就可以使用<code>typeof</code>运算符来检查一下结果.</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a;
console.log(typeof a);// 输出undefined类型
</pre>
</div>
<p>  </p>
<h2 id="number">Number</h2>
<p><code>Number</code>类型即为<code>数字类型</code>。</p>
<p>在<code>MDN</code>中关于<code>Number</code>类型的描述如下:</p>
<blockquote>
<p>根据 ECMAScript 标准,JavaScript 中只有一种数字类型:基于 IEEE 754 标准的双精度 64 位二进制格式的值(-(263 -1) 到 263 -1)。<strong>它并没有为整数给出一种特定的类型</strong>。除了能够表示浮点数外,还有一些带符号的值:<code>+Infinity</code>,<code>-Infinity</code>&nbsp;和&nbsp;<code>NaN</code>&nbsp;(非数值,Not-a-Number)。</p>
</blockquote>
<p>JavaScript 内部,所有数字都是以64位<code>浮点数</code>形式储存,即使整数也是如此。所以,<code>1</code>与<code>1.0</code>是相同的,是同一个数。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">1 === 1.0 // true
</pre>
</div>
<p>  </p>
<p>这就是说,JavaScript 语言的底层根本没有整数,所有数字都是小数(64位浮点数)。容易造成混淆的是,某些运算只有整数才能完成,此时 JavaScript 会自动把64位浮点数,转成32位整数,然后再进行运算。</p>
<p>由于<code>浮点数</code>不是精确的值,所以涉及小数的比较和运算要特别小心。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">0.1 + 0.2 === 0.3
// false

0.3 / 0.1
// 2.9999999999999996

(0.3 - 0.2) === (0.2 - 0.1)
// false
</pre>
</div>
<p>  </p>
<p><strong>数值范围:</strong></p>
<p>根据标准,64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则 JavaScript 能够表示的数值范围为21024到2-1023(开区间),超出这个范围的数无法表示。</p>
<p>如果一个数大于等于2的1024次方,那么就会发生“正向溢出”,即 JavaScript 无法表示这么大的数,这时就会返回<code>Infinity</code>。</p>
<p>如果一个数小于等于2的-1075次方(指数部分最小值-1023,再加上小数部分的52位),那么就会发生为“负向溢出”,即 JavaScript 无法表示这么小的数,这时会直接返回0。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">Math.pow(2, -1075) // 0
</pre>
</div>
<p>  </p>
<p>下面是一个实际的例子。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var x = 0.5;

for(var i = 0; i &lt; 25; i++) {
x = x * x;
}

x // 0
</pre>
</div>
<p>  </p>
<p>上面代码中,对<code>0.5</code>连续做25次平方,由于最后结果太接近0,超出了可表示的范围,JavaScript 就直接将其转为0。</p>
<p>而如果在<code>js</code>小于<strong>-1.7976931348623157E+103088</strong>&nbsp;的时候,就会表示为<code>-Infinity</code>.</p>
<p><strong>Number当中的特殊值:</strong></p>
<p>1、正零和负零</p>
<p>JavaScript 的64位浮点数之中,有一个二进制位是符号位。这意味着,任何一个数都有一个对应的负值,就连<code>0</code>也不例外。</p>
<p>JavaScript 内部实际上存在2个<code>0</code>:一个是<code>+0</code>,一个是<code>-0</code>,区别就是64位浮点数表示法的符号位不同。它们是等价的。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">-0 === +0 // true
0 === -0 // true
0 === +0 // true
</pre>
</div>
<p>  </p>
<p>几乎所有场合,正零和负零都会被当作正常的<code>0</code>。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">+0 // 0
-0 // 0
(-0).toString() // '0'
(+0).toString() // '0'
</pre>
</div>
<p>  </p>
<p>但是当<code>0</code>和<code>-0</code>被充当分母的时候,返回的值是不相等的。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">(1 / +0) === (1 / -0) // false
</pre>
</div>
<p>  </p>
<p>上面的代码之所以出现这样结果,是因为除以正零得到<code>+Infinity</code>,除以负零得到<code>-Infinity</code>,这两者是不相等的。</p>
<p>2、NaN</p>
<p><code>NaN</code>是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">console.log(5 - 'x'); //NaN
</pre>
</div>
<p>  </p>
<p>需要注意的是,<code>NaN</code>不是独立的数据类型,而是一个特殊数值,它的数据类型依然属于<code>Number</code>,使用<code>typeof</code>运算符可以看得很清楚。</p>
<blockquote>
<p>需要注意,<code>NaN</code>是一个非常<code>狠</code>的角色,它连自己都不认,也就是说,如果你判断<code>NaN</code>是否等于<code>NaN</code>,答案是否定的,也就是<code>false</code>,二者根本不想等。</p>
</blockquote>
<p>3、Infinity</p>
<p><code>Infinity</code>表示为<code>无穷大</code>。在<code>js</code>中,如果数值的内容超过了<code>js</code>所能表示的范围,就会输出<code>Infinity</code>或者<code>-Infinity</code>。</p>
<p><strong>Number当中的全局方法:</strong></p>
<p>1、<code>parseInt()</code></p>
<p><code>parseInt</code>方法用于将字符串转为整数。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseInt('123') // 123
</pre>
</div>
<p>  </p>
<p>如果字符串头部有空格,空格会被自动去除。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseInt('   81') // 81
</pre>
</div>
<p>  </p>
<p>如果<code>parseInt</code>的参数不是字符串,则会先转为字符串再转换。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseInt(1.23) // 1
// 等同于
parseInt('1.23') // 1
</pre>
</div>
<p>  </p>
<p>字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseInt('8a') // 8
parseInt('12**') // 12
parseInt('12.34') // 12
parseInt('15e2') // 15
parseInt('15px') // 15
</pre>
</div>
<p>  </p>
<p>上面代码中,<code>parseInt</code>的参数都是字符串,结果只返回字符串头部可以转为数字的部分。</p>
<p>如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回<code>NaN</code>。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseInt('abc') // NaN
parseInt('.3') // NaN
parseInt('') // NaN
parseInt('+') // NaN
parseInt('+1') // 1
</pre>
</div>
<p>  </p>
<p>所以,<code>parseInt</code>的返回值只有两种可能,要么是一个十进制整数,要么是<code>NaN</code>。</p>
<p><strong>2、<code>parseFloat()</code></strong></p>
<p><code>parseFloat</code>方法用于将一个字符串转为浮点数。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseFloat('3.14') // 3.14
</pre>
</div>
<p>  </p>
<p>如果字符串符合科学计数法,则会进行相应的转换。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseFloat('314e-2') // 3.14
parseFloat('0.0314E+2') // 3.14
</pre>
</div>
<p>  </p>
<p>如果字符串包含不能转为浮点数的字符,则不再进行往后转换,返回已经转好的部分。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseFloat('3.14more non-digit characters') // 3.14
</pre>
</div>
<p>  </p>
<p><code>parseFloat</code>方法会自动过滤字符串前导的空格。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseFloat('\t\v\r12.34\n ') // 12.34
</pre>
</div>
<p>  </p>
<p>如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回<code>NaN</code>。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseFloat([]) // NaN
parseFloat('FF2') // NaN
parseFloat('') // NaN
parseFloat('1avc') // 1
parseFloat('a1') // NaN
</pre>
</div>
<p>  </p>
<p>上面代码中,尤其值得注意,<code>parseFloat</code>会将空字符串转为<code>NaN</code>。</p>
<p>这些特点使得<code>parseFloat</code>的转换结果不同于<code>Number</code>函数。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">parseFloat(true)// NaN
Number(true) // 1

parseFloat(null) // NaN
Number(null) // 0

parseFloat('') // NaN
Number('') // 0

parseFloat('123.45#') // 123.45
Number('123.45#') // NaN
</pre>
</div>
<p>  </p>
<p>3、<strong>isNaN()</strong></p>
<p><code>isNaN</code>方法可以用来判断一个值是否为<code>NaN</code>。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">isNaN(NaN) // true
isNaN(123) // false
</pre>
</div>
<p>  </p>
<p>但是,<code>isNaN</code>只对数值有效,如果传入其他值,会被先转成数值。比如,传入字符串的时候,字符串会被先转成<code>NaN</code>,所以最后返回<code>true</code>,这一点要特别引起注意。也就是说,<code>isNaN</code>为<code>true</code>的值,有可能不是<code>NaN</code>,而是一个字符串。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">isNaN('Hello') // true
// 相当于
isNaN(Number('Hello')) // true
</pre>
</div>
<p>  </p>
<p><strong>4、isFinite()</strong></p>
<p><code>isFinite</code>方法返回一个布尔值,表示某个值是否为正常的数值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(undefined) // false
isFinite(null) // true
isFinite(-1) // true
</pre>
</div>
<p>  </p>
<p>除了<code>Infinity</code>、<code>-Infinity</code>、<code>NaN</code>和<code>undefined</code>这几个值会返回<code>false</code>,<code>isFinite</code>对于其他的数值都会返回<code>true</code>。</p>
<h2 id="string">String</h2>
<p>将<code>0</code>个或者<code>任意多</code>个字符排列起来放在<code>单引号</code>或者<code>双引号</code>当中,就是一个<code>字符串(String)</code>。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = "hello,world!";
var b = 'hello,JavaScript!';
</pre>
</div>
<p>  </p>
<p>上面的变量<code>a</code>和<code>b</code>当中存储的数据就是<code>字符串</code>,其中一个使用了单引号,一个使用了双引号,两者都是合法的。</p>
<p>单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">'key = "value"'
"It's a long journey"
</pre>
</div>
<p>  </p>
<p>如果要在单引号字符串的内部,使用单引号,就必须在内部的单引号前面加上反斜杠,用来转义。双引号字符串内部使用双引号,也是如此。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">'Did she say \'Hello\'?'
// "Did she say 'Hello'?"

"Did she say \"Hello\"?"
// "Did she say "Hello"?"
</pre>
</div>
<p>  </p>
<p>由于 HTML 语言的属性值使用<code>双引号</code>,所以很多项目约定<code>JavaScript</code>语言的字符串只使用<code>单引号</code>,在这套系列教程中会遵守这个约定。当然,只使用双引号也完全可以。重要的是坚持使用一种风格,不要一会使用单引号表示字符串,一会又使用双引号表示。</p>
<p>字符串默认只能写在一行内,分成多行将会报错。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">'a
b
c'
// SyntaxError: Unexpected token ILLEGAL
</pre>
</div>
<p>  </p>
<p>上面代码将一个字符串分成三行,JavaScript 就会报错。</p>
<p>如果长字符串必须分成多行,可以在每一行的尾部使用反斜杠。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var longString = 'Long \
long \
long \
string';

longString
// "Long long long string"
</pre>
</div>
<p>  </p>
<p>上面代码表示,加了反斜杠以后,原来写在一行的字符串,可以分成多行书写。但是,输出的时候还是单行,效果与写在同一行完全一样。注意,反斜杠的后面必须是换行符,而不能有其他字符(比如空格),否则会报错。</p>
<p>连接运算符(<code>+</code>)可以连接多个单行字符串,将长字符串拆成多行书写,输出的时候也是单行。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var longString = 'Long '
+ 'long '
+ 'long '
+ 'string';
</pre>
</div>
<p>  </p>
<p><strong>转义字符:</strong></p>
<p>反斜杠()在字符串内有特殊含义,用来表示一些特殊字符,所以又称为转义符。</p>
<p>需要用反斜杠转义的特殊字符,主要有下面这些。</p>
<ul>
<li><code>\0</code>&nbsp;:null(<code>\u0000</code>)</li>
<li><code>\b</code>&nbsp;:后退键(<code>\u0008</code>)</li>
<li><code>\f</code>&nbsp;:换页符(<code>\u000C</code>)</li>
<li><code>\n</code>&nbsp;:换行符(<code>\u000A</code>)</li>
<li><code>\r</code>&nbsp;:回车键(<code>\u000D</code>)</li>
<li><code>\t</code>&nbsp;:制表符(<code>\u0009</code>)</li>
<li><code>\v</code>&nbsp;:垂直制表符(<code>\u000B</code>)</li>
<li><code>\'</code>&nbsp;:单引号(<code>\u0027</code>)</li>
<li><code>\"</code>&nbsp;:双引号(<code>\u0022</code>)</li>
<li><code>\\</code>&nbsp;:反斜杠(<code>\u005C</code>)</li>
</ul>
<p>如果在一个正常的字符前面加了<code>\</code>,是没有效果的。</p>
<pre class="js"><code class="hljs javascript"><span class="hljs-built_in">console.log(<span class="hljs-string">"\a"); <span class="hljs-comment">//输出a</span></span></span></code></pre>
<h2 id="运算符">运算符</h2>
<p>在编程语言当中,运算符是处理数据的基本方法,能够根据现有的值得到新的值。</p>
<p>在<code>JavaScript</code>当中,存在下列的运算符。</p>
<ul>
<li>赋值运算符</li>
<li>比较运算符</li>
<li>算数运算符</li>
<li>位运算符</li>
<li>逻辑运算符</li>
<li>字符串运算符</li>
<li>条件(三元)运算符</li>
<li>逗号运算符</li>
<li>一元运算符</li>
<li>关系运算符</li>
</ul>
<p>下面我们将逐一的来讲解不同的运算符。</p>
<blockquote>
<p>这一部分很枯燥,请做好心理准备!</p>
</blockquote>
<h3 id="赋值运算符">赋值运算符</h3>
<p>赋值运算符(<strong>assignment operator</strong>)基于右值(right operand)的值,给左值(left operand)赋值。</p>
<p>在之前的内容中,我们通过下面的写法来创建变量。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = 10;
</pre>
</div>
<p>  </p>
<p>上面我们通过<code>=</code>来将右边的<code>10</code>存储到左边的变量a身上。而这种操作,我们在编程当中称之为<code>赋值</code>。</p>
<p>而<code>=</code>也就是<code>赋值运算符</code>。也可以使用链式赋值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = b = c = 15;
console.log(a,b,c);//15,15,15
</pre>
</div>
<p>  </p>
<p>顺序是从右向左的进行赋值操作。</p>
<p>下面的列表中包含全部的<code>赋值运算符</code>。</p>
<ul>
<li>赋值&nbsp;<code>x = y</code></li>
<li>加赋值&nbsp;<code>x += y</code></li>
<li>减赋值&nbsp;<code>x -= y</code></li>
<li>乘赋值&nbsp;<code>x *= y</code></li>
<li>除赋值&nbsp;<code>x /= y</code></li>
<li>模赋值&nbsp;<code>x %= y</code></li>
<li>指数赋值&nbsp;<code>x **= y</code></li>
<li>左移赋值&nbsp;<code>x &lt;&lt;= y</code></li>
<li>右移赋值&nbsp;<code>x &gt;&gt;= y</code></li>
<li>无符号右移赋值&nbsp;<code>x &gt;&gt;&gt;= y</code></li>
<li>按位与赋值&nbsp;<code>x &amp;= y</code></li>
<li>按位异或赋值&nbsp;<code>x ^= y</code></li>
<li>按位或赋值&nbsp;<code>x |= y</code></li>
</ul>
<h4 id="赋值">赋值</h4>
<p>简单的赋值运算符,把一个值赋给一个变量。为了把一个值赋给多个变量,可以以链式使用赋值运算符。</p>
<h4 id="加赋值">加赋值</h4>
<p>加赋值运算符<code>把一个右值与一个变量</code>相加,然后把相加的结果赋给该变量。两个操作数的类型决定了加赋值运算符的行为。算术相加或字符串连接都有可能。</p>
<p>例如:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var x = 10;
var y = 20;
x += y;
console.log(x);
// 相当于
x = x + y;
</pre>
</div>
<p>  </p>
<h4 id="减赋值">减赋值</h4>
<p>减赋值运算符使一个变量减去右值,然后把结果赋给该变量。</p>
<p>例如:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var x = 10;
var y = 20;
x -= y;
console.log(x); // -10
// 相当于
x = x - y;
</pre>
</div>
<p>  </p>
<h4 id="乘赋值">乘赋值</h4>
<p>乘赋值运算符使一个变量乘以右值,然后把相成的结果赋给该变量。</p>
<p>例如:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var x = 10;
var y = 20;
x *= y;
console.log(x); // 200
// 相当于
x = x * y;
</pre>
</div>
<p>  </p>
<h4 id="除赋值">除赋值</h4>
<p>除赋值运算符使一个变量除以右值,然后把结果赋给该变量。</p>
<p>例如:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = 10;
var b = 20;
a /= b;
console.log(a);
// 相当于
a = a / b;
</pre>
</div>
<p>  </p>
<h4 id="模赋值">模赋值</h4>
<p>模赋值运算符使一个变量除以右值,然后把余数交给该变量。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var x = 10;
var y = 20;
a %= b;
console.log(a);
//等同于
a = a % b;
</pre>
</div>
<p>  </p>
<h4 id="指数赋值">指数赋值</h4>
<p>指数赋值运算符使一个变量为底数、以右值为指数的指数运算(乘方)结果赋给该变量。</p>
<p>例如:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var x = 2;
var y = 3;
x **= y;
console.log(x); // 8
// 相当于
x = x ** y
</pre>
</div>
<p>  </p>
<blockquote>
<p>剩下的放在后面说到进制的时候再来说。</p>
</blockquote>
<h3 id="比较运算符">比较运算符</h3>
<p>比较运算符包括下列内容:</p>
<ul>
<li>等于&nbsp;<code>==</code>&nbsp;如果两边操作数相等时返回true。</li>
<li>不等于&nbsp;<code>!=</code>&nbsp;如果两边操作数不相等时返回true</li>
<li>全等&nbsp;<code>===</code>&nbsp;两边操作数相等且类型相同时返回true。</li>
<li>不全等<code>!==</code>&nbsp;两边操作数不相等或类型不同时返回true。</li>
<li>大于<code>&gt;</code>&nbsp;左边的操作数大于右边的操作数返回true</li>
<li>大于等于<code>&gt;=</code>&nbsp;左边的操作数大于或等于右边的操作数返回true</li>
<li>小于<code>&lt;</code>&nbsp;左边的操作数小于右边的操作数返回true</li>
<li>小于等于<code>&lt;=</code>&nbsp;左边的操作数小于或等于右边的操作数返回true</li>
</ul>
<blockquote>
<p><code>=&gt;</code>&nbsp;并不是一个运算符,而是箭头函数。</p>
</blockquote>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">/*
下面是比较运算符的示例:
*/
// == 相等运算符
console.log(10 == 10); // true
console.log(20 == "20"); // true

// != 不等运算符
console.log(3 != 2); // true
console.log(2 != "hello"); // true

// === 全等
console.log(3 === 3);// true
console.log(3 === "3"); // false值虽然相等,但是类型不相等。

// !== 不全等
console.log(3 !== "3");// true
console.log(3 !== 2); // true

// &gt; 大于
console.log(3 &gt; 2); // true
console.log("3" &gt; "4");// false   

// &lt; 小于
console.log(2 &lt; 1); // false
console.log(3 &lt; 4); // true

// &gt;= 大于等于
// &lt;= 小于等于
console.log(2 &gt;= 1); // true
console.log(2 &gt;= 2); // true
console.log(3 &lt;= 3); // true
console.log(3 &lt;= 4); // true
</pre>
</div>
<p>  </p>
<h3 id="算数运算符">算数运算符</h3>
<p>在<code>js</code>当中,除了提供基础的<code>+</code>,<code>-</code>,<code>*</code>,<code>/</code>以外,还提供了一些其他的运算符,下面是所有的算术运算符:</p>
<ul>
<li><code>+</code>加法运算</li>
<li><code>-</code>&nbsp;减法运算</li>
<li><code>*</code>乘法运算</li>
<li><code>/</code>&nbsp;除法运算</li>
<li><code>%</code>求余运算(求模运算)</li>
<li><code>++</code>自增运算</li>
<li><code>--</code>自减运算</li>
<li><code>+</code>一元正值符</li>
<li><code>-</code>一元负值符</li>
<li><code>**</code>指数运算符</li>
</ul>
<p>例子:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">/*
      下面是一些算数运算符的案例:
   */
   
    var a,b;
    a = 10;
    b = 3;

    console.log(a + b); // 13
    console.log(a - b); // 7
    console.log(a * b); // 30
    console.log(a / b); // 3.3333333333333335


    console.log(a % b); // 1
    console.log(++a); // 11自增|自减符号在前,则先运算,在使用值
    console.log(a++); // 11 自增|自减符号在后,则先使用值,在运算
    console.log(a); // 12// 上面a++后a由11变成了12

    // 一元正值符,如果操作数不是Number,则尝试着将操作数转换为Number
    var c = "3";
    console.log(+c,typeof +c); // 3 number

    // 一元负值负,将一个值变为负数
    var d = 3;
    console.log(-d); // -3

    var e = '3';
    console.log(-e,typeof -e); //-3 number 也起到了转换的效果

    console.log(-3 === -e); // true

    // 指数运算符
    var f = 2;
    var x = 3;

    console.log(f ** x); // 8 相当于2 的 3 次幂
</pre>
</div>
<p>  </p>
<h3 id="逻辑运算符">逻辑运算符</h3>
<p>逻辑运算符常用于布尔(逻辑)值之间; 当操作数都是布尔值时,返回值也是布尔值。 不过实际上<code>&amp;&amp;</code>和<code>||</code>返回的是一个特定的操作数的值,所以当它用于非布尔值的时候,返回值就可能是非布尔值。</p>
<p>下面是逻辑运算符:</p>
<ul>
<li>逻辑与<code>(&amp;&amp;)</code></li>
<li>逻辑或<code>(||)</code></li>
<li>逻辑非<code>(!)</code></li>
</ul>
<p><strong>逻辑与:</strong></p>
<p><code>逻辑与&amp;&amp;</code>运算符又称为<code>且运算符</code>,往往用于多个表达式之间的求值。</p>
<p>它的运算规则是:如果第一个运算子的布尔值为<code>true</code>,则返回第二个运算子的值(注意是值,不是布尔值);如果第一个运算子的布尔值为<code>false</code>,则直接返回第一个运算子的值,且不再对第二个运算子求值。</p>
<p>语法:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">exrp1 &amp;&amp; exrp2;
</pre>
</div>
<p>  </p>
<p><strong>逻辑或:</strong></p>
<p><code>逻辑或||</code>运算符又称为<code>或运算符</code>,同样用于在多个表达式之间求值。</p>
<p>它的运算规则是:如果第一个运算子的布尔值为<code>true</code>,则返回第一个运算子的值,且不再对第二个运算子求值;如果第一个运算子的布尔值为<code>false</code>,则返回第二个运算子的值。</p>
<p>语法:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">exrp1 || exrp2
</pre>
</div>
<p>  </p>
<p>例如:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">// 逻辑与
    // 当运算符的前后都为条件语句的时候,当条件同时为true,则返回true,否则返回false
    var a = 1;
    var b = 2;
    console.log(a &gt; 0 &amp;&amp; b &gt; a); //true 第一个条件判断为true,第二个条件判断为true,那么整体返回true
    console.log(a &gt; b &amp;&amp; b &gt; 1); // false 第一个条件判断为false,第二个条件判断为true,整体返回false
    console.log(a &gt; 0 &amp;&amp; b &gt; 2); // false 第一个条件为true,第二个条件为false,整体返回false
    //
    console.log("dog" &amp;&amp; "cat"); // cat当运算符的前后是一个直接量的时候,如果运算符前后都为true,则返回第二个直接量   
    // 逻辑或
    console.log(a &gt; b || b &gt; a); //true 其中只要有一个条件成立,那么就会返回true
    console.log(a &gt; 2 || b &gt; 2); // false 两个条件都不成立,所以返回fasle
    // 第一个条件如果成立,那么就不会去读取后面的条件
    console.log(a &gt; 0 || b &gt; 2); // true
</pre>
</div>
<p>  </p>
<p>在上面的两个逻辑运算符的使用过程中,容易造成<code>短路效果</code>。</p>
<ul>
<li><code>false</code>&nbsp;&amp;&amp;&nbsp;<em>anything</em>&nbsp;// 被短路求值为false</li>
<li><code>true</code>&nbsp;||&nbsp;<em>anything</em>&nbsp;// 被短路求值为true</li>
</ul>
<p>在上面的短路代码中,anything部分不会被求值,也就意味着不会对代码产生任何的影响。</p>
<p><strong>逻辑与运算符和逻辑或的连用:</strong></p>
<p>逻辑与运算符可以多个连用,这时返回第一个布尔值为<code>false</code>的表达式的值。如果所有表达式的布尔值都为<code>true</code>,则返回最后一个表达式的值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">true &amp;&amp; 'foo' &amp;&amp; '' &amp;&amp; 4 &amp;&amp; 'foo' &amp;&amp; true
// ''

1 &amp;&amp; 2 &amp;&amp; 3
// 3
</pre>
</div>
<p>  </p>
<p>上面代码中,例一里面,第一个布尔值为<code>false</code>的表达式为第三个表达式,所以得到一个空字符串。例二里面,所有表达式的布尔值都是<code>true</code>,所有返回最后一个表达式的值<code>3</code>。</p>
<p>运算符可以多个连用,这时返回第一个布尔值为<code>true</code>的表达式的值。如果所有表达式都为<code>false</code>,则返回最后一个表达式的值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">false || 0 || '' || 4 || 'foo' || true
// 4

false || 0 || ''
// ''
</pre>
</div>
<p>  </p>
<p>上面代码中,例一里面,第一个布尔值为<code>true</code>的表达式是第四个表达式,所以得到数值4。例二里面,所有表达式的布尔值都为<code>false</code>,所以返回最后一个表达式的值。</p>
<p><code>逻辑或运算符</code>通常情况下用于给一个变量设置默认值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = username || "zhangsan";
</pre>
</div>
<p>  </p>
<p><strong>逻辑非:</strong></p>
<p><code>逻辑非(!)</code>运算符又叫<code>取反运算符</code>,就是取一个值的反值。主要用于将一个布尔值变为相反值。即<code>true</code>变为<code>false</code>,<code>false</code>变为<code>true</code>。</p>
<p>如果使用取反运算符的值不是一个布尔值,那么取反运算符就会将其变为一个布尔值,然后再取反。</p>
<p>下面的六个值使用取反运算符取反后都为<code>true</code>,其他都为<code>false</code>。</p>
<ul>
<li><code>undefined</code></li>
<li><code>null</code></li>
<li><code>false</code></li>
<li><code>0</code></li>
<li><code>NaN</code></li>
<li>空字符串<code>('')</code></li>
</ul>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">!undefined // true
!null // true
!0 // true
!NaN // true
!"" // true

!54 // false
!'hello' // false
![] // false
!{} // false
</pre>
</div>
<p>  </p>
<p>不管什么类型的值,经过取反运算后都会变成布尔值。</p>
<blockquote>
<p>如果对一个值连续做两次的取反运算,等于将其转换为对应的布尔值,与<code>Boolean</code>函数的作用相同。这是一种较为常见的类型转换的方法。</p>
<p>例如:</p>
<pre class="js"><code class="hljs javascript"><span class="hljs-keyword">var a = <span class="hljs-string">"hello";
<span class="hljs-built_in">console.log(!!a); <span class="hljs-comment">// true </span></span></span></span></code></pre>
</blockquote>
<h3 id="字符串运算符">字符串运算符</h3>
<p><code>字符串运算符</code>指的是<code>+</code>,通过加号,我们可以对两个字符串进行拼接从而返回一个新的字符串。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = "hello,";
var b = "world!";
console.log(a + b); // hello,world!
</pre>
</div>
<p>  </p>
<p>也可以采用简写的形式来拼接字符串。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var str = "hello,";
var str += "world!";
console.log(str); // hello,world!
</pre>
</div>
<p>  </p>
<p>我们也可以在使用的过程中进行数据的拼接。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var sayHello = "hello,my name is ";
console.log(sayHello + "zhangsan");// hello,my name is zhangsan
</pre>
</div>
<p>  </p>
<h3 id="条件运算符">条件运算符</h3>
<p><code>条件运算符</code>也称之为<code>三元运算符</code>。</p>
<p>条件运算符是JavaScript中唯一需要三个操作数的运算符。运算的结果根据给定条件在两个值中取其一。语法为:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">条件 ? 值1 : 值2
</pre>
</div>
<p>  </p>
<p>如果<code>条件</code>为真,则结果取<code>值1</code>。否则为<code>值2</code>。你能够在任何允许使用标准运算符的地方使用条件运算符。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var status = (age &gt;= 18) ? "adult" : "minor";
</pre>
</div>
<p>  </p>
<p>当&nbsp;<code>age</code>&nbsp;大于等于18的时候,将“adult”赋值给<code>status</code>;否则将“minor”赋值给&nbsp;<code>status</code>。</p>
<h3 id="逗号运算符">逗号运算符</h3>
<p>逗号操作符(,)对两个操作数进行求值并返回最终操作数的值。它常常用在 for 循环中,在每次循环时对多个变量进行更新。</p>
<p>当然,我们在<code>console.log()</code>的过程中,如果输出多个值,也会用到逗号运算符。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">console.log("hello","world");
</pre>
</div>
<p>  </p>
<h3 id="一元操作符">一元操作符</h3>
<p>一元操作符仅对应一个操作数。</p>
<p>常用的一元操作符有如下几个:</p>
<ul>
<li>delete</li>
<li>typeof</li>
<li>void</li>
</ul>
<p><code>delete</code>主要用于删除对象当中的某个元素。</p>
<p><code>void</code>主要用于表明一个运算没有返回值。</p>
<p>例如:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
delete trees; // 删除数组当中的一个元素

&lt;a href="javascript:void(0)"&gt;Click here to do nothing&lt;/a&gt; // 用户点击这个链接不会有任何效果
</pre>
</div>
<p>  </p>
<blockquote>
<p>上面的demo中的两个运算符,我们暂时还没有用到,所以可以先放在这,后面再来理解。</p>
</blockquote>
<p>至于<code>typeof</code>运算符,主要用来查看数据的类型,将获取的数据类型以一个字符串的形式展示出来。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = "hello,world!";
console.log(typeof a); // "string"

var b = 13;
console.log(typeof (b)); // "number"
</pre>
</div>
<p>  </p>
<p>在上面的demo中,我们发现<code>typeof</code>有两种使用方式。运算符后面的括号可以选择省略或者不省略。</p>
<p>案例:</p>
<pre class="js"></pre>
<h3 id="关系操作符">关系操作符</h3>
<p>关系操作符对操作数进行比较,根据比较结果真或假,返回相应的布尔值。</p>
<p>下面是<code>关系操作符</code>的具体内容:</p>
<ul>
<li>
<p><code>in</code></p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">console.log(typeof "hello,world"); // "string"
console.log(typeof 10); // "number"
console.log(typeof true); // "boolean"
console.log(typeof false); // "boolean"
console.log(typeof null); // "object"
console.log(typeof undefined); // "undefined"

// 查看typeof返回的数据的类型
console.log(typeof typeof(10)); // "string"
</pre>
</div>
<p>  </p>
</li>
<li>
<h4 id="instanceof"><code>instanceof</code></h4>
</li>
</ul>
<h3 id="运算符优先级">运算符优先级</h3>
<p>运算符的优先级,用于确定一个表达式的计算顺序。在你不能确定优先级时,可以通过使用<strong>括号显式声明运算符的优先级</strong>。</p>
<p>下表列出了描述符的优先级,从最高到最低。</p>
<table>
<thead>
<tr class="header"><th>Operator type</th><th>Individual operators</th></tr>
</thead>
<tbody>
<tr class="odd">
<td>member</td>
<td><code>. []</code></td>
</tr>
<tr class="even">
<td>call / create instance</td>
<td><code>() new</code></td>
</tr>
<tr class="odd">
<td>negation/increment</td>
<td><code>! ~ - + ++ -- typeof void delete</code></td>
</tr>
<tr class="even">
<td>multiply/divide</td>
<td><code>* / %</code></td>
</tr>
<tr class="odd">
<td>addition/subtraction</td>
<td><code>+ -</code></td>
</tr>
<tr class="even">
<td>bitwise shift</td>
<td><code>&lt;&lt; &gt;&gt; &gt;&gt;&gt;</code></td>
</tr>
<tr class="odd">
<td>relational</td>
<td><code>&lt; &lt;= &gt; &gt;= in instanceof</code></td>
</tr>
<tr class="even">
<td>equality</td>
<td><code>== != === !==</code></td>
</tr>
<tr class="odd">
<td>bitwise-and</td>
<td><code>&amp;</code></td>
</tr>
<tr class="even">
<td>bitwise-xor</td>
<td><code>^</code></td>
</tr>
<tr class="odd">
<td>bitwise-or</td>
<td><code>|</code></td>
</tr>
<tr class="even">
<td>logical-and</td>
<td><code>&amp;&amp;</code></td>
</tr>
<tr class="odd">
<td>logical-or</td>
<td><code>||</code></td>
</tr>
<tr class="even">
<td>conditional</td>
<td><code>?:</code></td>
</tr>
<tr class="odd">
<td>assignment</td>
<td><code>= += -= *= /= %= &lt;&lt;= &gt;&gt;= &gt;&gt;&gt;= &amp;= ^= |=</code></td>
</tr>
<tr class="even">
<td>comma</td>
<td><code>,</code></td>
</tr>
</tbody>
</table>
<h2 id="数据类型转换">数据类型转换</h2>
<p>JavaScript 是一种动态类型语言,变量没有类型限制,可以随时赋予任意值。</p>
<p>例如:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = 10; // 创建一个变量a,并且赋值为10
a = "hello,world!"; // 将"hello,world"重新赋值给变量a,这样a就由number变为string
</pre>
</div>
<p>  </p>
<p>再来看下面这个案例:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var x = y ? 1 : 'a';
</pre>
</div>
<p>  </p>
<p>上面代码中,变量<code>x</code>到底是数值还是字符串,取决于另一个变量<code>y</code>的值。<code>y</code>为<code>true</code>时,<code>x</code>是一个数值;<code>y</code>为<code>false</code>时,<code>x</code>是一个字符串。这意味着,<code>x</code>的类型没法在编译阶段就知道,必须等到运行时才能知道。</p>
<p>虽然变量的数据类型是不确定的,但是各种运算符对数据类型是有要求的。如果运算符发现,运算子的类型与预期不符,就会自动转换类型。比如,减法运算符预期左右两侧的运算子应该是数值,如果不是,就会自动将它们转为数值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">'4' - '3' // 1
</pre>
</div>
<p>  </p>
<p>上面代码中,虽然是两个字符串相减,但是依然会得到结果数值<code>1</code>,原因就在于 JavaScript 将运算子自动转为了数值。</p>
<p>在章节,我们将会先来讲解<code>手动强制类型转换数据类型</code>,接着会说到<code>数据类型的自动转换规则</code>。</p>
<h3 id="强制类型转换">强制类型转换</h3>
<p>强制转换主要指使用<code>Number()</code>、<code>String()</code>和<code>Boolean()</code>三个函数,手动将各种类型的值,分别转换成数字、字符串或者布尔值。</p>
<h4 id="number-1">Number()</h4>
<p>使用<code>Number</code>函数,可以将任意类型的值转化成数值。</p>
<p>下面分成两种情况讨论,一种是参数是原始类型的值,另一种是参数是对象。</p>
<p><strong>原始类型值:</strong></p>
<p>下面通过案例来演示一下原始类型值转换为Number类型的规则:</p>
<pre class="js"></pre>
<blockquote>
<p>Number函数会自动过滤一个字符串前导和后缀的空格。</p>
</blockquote>
<p><strong>对象:</strong><br>简单的规则是,Number方法的参数是对象时,将返回NaN,除非是包含单个数值的数组。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">Number({a: 1}) // NaN
Number() // NaN
Number() // 5
</pre>
</div>
<p>  </p>
<h4 id="string-1">String()</h4>
<p><code>String</code>函数可以将任意类型的值转化成字符串,转换规则如下。<br>(1)原始类型值</p>
<ul>
<li>数值:转为相应的字符串。</li>
<li>字符串:转换后还是原来的值。</li>
<li>布尔值:true转为字符串"true",false转为字符串"false"。</li>
<li>undefined:转为字符串"undefined"。</li>
<li>null:转为字符串"null"。</li>





</ul>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">String(123) // "123"
String('abc') // "abc"
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"
</pre>
</div>
<p>  </p>
<p><strong>(2)对象:</strong></p>
<p><code>String</code>方法的参数如果是对象,返回一个类型字符串;如果是数组,返回该数组的字符串形式。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">String({a: 1}) // ""
String() // "1,2,3"
</pre>
</div>
<p>  </p>
<h4 id="boolean-1">Boolean()</h4>
<p><code>Boolean()</code>函数可以将任意类型的值转为布尔值。</p>
<p>它的转换规则相对简单:除了以下五个值的转换结果为<code>false</code>,其他的值全部为<code>true</code>。</p>
<ul>
<li><code>undefined</code></li>
<li><code>null</code></li>
<li><code>0</code>(包含<code>-0</code>和<code>+0</code>)</li>
<li><code>NaN</code></li>
<li><code>''</code>(空字符串)</li>
</ul>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
</pre>
</div>
<p>  </p>
<p>当然,<code>true</code>和<code>false</code>这两个布尔值不会发生变化。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">Boolean(true) // true
Boolean(false) // false
</pre>
</div>
<p>  </p>
<p>注意,所有对象(包括空对象)的转换结果都是<code>true</code>,甚至连<code>false</code>对应的布尔对象<code>new Boolean(false)</code>也是<code>true</code></p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true
</pre>
</div>
<p>  </p>
<p>所有对象的布尔值都是<code>true</code>,这是因为 JavaScript 语言设计的时候,出于性能的考虑,如果对象需要计算才能得到布尔值,对于<code>obj1 &amp;&amp; obj2</code>这样的场景,可能会需要较多的计算。为了保证性能,就统一规定,对象的布尔值为<code>true</code>。</p>
<h3 id="自动类型转换">自动类型转换</h3>
<p>上面说完了强制类型转换,再来说下自动类型转换,它是以强制类型转换为基础的。</p>
<p>遇到以下三种情况时,JavaScript 会自动转换数据类型,即转换是自动完成的,用户不可见。</p>
<p>第一种情况,不同类型的数据互相运算。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">123 + 'abc' // "123abc"
</pre>
</div>
<p>  </p>
<p>第二种情况,对非布尔值类型的数据求布尔值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">if ('abc') {
console.log('hello')
}
</pre>
</div>
<p>  </p>
<p>第三种情况,对非数值类型的值使用一元运算符(即<code>+</code>和<code>-</code>)。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var a = "10";
console.log(+ a,typeof +a); // 10 "number"
+ {foo: 'bar'} // NaN
- // NaN
</pre>
</div>
<p>  </p>
<p>自动转换的规则是这样的:预期什么类型的值,就调用该类型的转换函数。比如,某个位置预期为字符串,就调用<code>String</code>函数进行转换。如果该位置即可以是字符串,也可能是数值,那么默认转为数值。</p>
<p><strong>由于自动转换具有不确定性,而且不易除错,建议在预期为布尔值、数值、字符串的地方,全部使用<code>Boolean</code>、<code>Number</code>和<code>String</code>函数进行显式转换。</strong></p>
<h4 id="自动转换为布尔值">自动转换为布尔值</h4>
<p>JavaScript 遇到预期为布尔值的地方(比如<code>if</code>语句的条件部分),就会将非布尔值的参数自动转换为布尔值。系统内部会自动调用<code>Boolean</code>函数。</p>
<p>因此除了以下五个值,其他都是自动转为<code>true</code>。</p>
<ul>
<li><code>undefined</code></li>
<li><code>null</code></li>
<li><code>+0</code>或<code>-0</code></li>
<li><code>NaN</code></li>
<li><code>''</code>(空字符串)</li>
</ul>
<p>下面这个例子中,条件部分的每个值都相当于<code>false</code>,使用否定运算符后,就变成了<code>true</code>。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">if ( !undefined
&amp;&amp; !null
&amp;&amp; !0
&amp;&amp; !NaN
&amp;&amp; !''
) {
console.log('true');
} // true
</pre>
</div>
<p>  </p>
<p>下面两种写法,有时也用于将一个表达式转为布尔值。它们内部调用的也是<code>Boolean</code>函数。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">// 写法一
expression ? true : false

// 写法二
!! expression
</pre>
</div>
<p>  </p>
<h4 id="自动转换为字符串">自动转换为字符串</h4>
<p>JavaScript 遇到预期为字符串的地方,就会将非字符串的值自动转为字符串。具体规则是,先将复合类型的值转为原始类型的值,再将原始类型的值转为字符串。</p>
<p>字符串的自动转换,主要发生在字符串的加法运算时。当一个值为字符串,另一个值为非字符串,则后者转为字符串。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
</pre>
</div>
<p>  </p>
<p>这种自动转换很容易出错。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">var obj = {
width: '100'
};

obj.width + 20 // "10020"
</pre>
</div>
<p>  </p>
<p>上面代码中,开发者可能期望返回<code>120</code>,但是由于自动转换,实际上返回了一个字符<code>10020</code>。</p>
<h4 id="自动转换为数值">自动转换为数值</h4>
<p>JavaScript 遇到预期为数值的地方,就会将参数值自动转换为数值。系统内部会自动调用<code>Number</code>函数。</p>
<p>除了加法运算符(<code>+</code>)有可能把运算子转为字符串,其他运算符都会把运算子自动转成数值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">'5' - '2' // 3
'5' * '2' // 10
true - 1// 0
false - 1 // -1
'1' - 1   // 0
'5' * []    // 0
false / '5' // 0
'abc' - 1   // NaN
null + 1 // 1
undefined + 1 // NaN
</pre>
</div>
<p>  </p>
<p>上面代码中,运算符两侧的运算子,都被转成了数值。</p>
<blockquote>
<p>注意:<code>null</code>转为数值时为<code>0</code>,而<code>undefined</code>转为数值时为<code>NaN</code>。</p>
</blockquote>
<p>一元运算符也会把运算子转成数值。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0
</pre>
</div>
<p>  </p>
<p>&nbsp;</p>
<h3 data-id="heading-5">如果大家有任何疑问即可留言反馈,会在第一时间回复反馈,谢谢大家!</h3>
<h3 data-id="heading-5">本人使用GSAP框架搭建的个人网站也上线啦!有兴趣可以访问&nbsp;zhaohongcheng.com&nbsp;查看,感谢~</h3>
<h3 data-id="heading-5">本人uni-app影视项目已经重磅开源,一套代码套发布到H5、APP、小程序等多个平台!有兴趣可以访问Dcloud官方插件市场https://ext.dcloud.net.cn/plugin?id=1839&nbsp;查看,感谢~</h3>
<h3>本文为Tz张无忌文章,读后有收获可以请作者喝杯咖啡,转载请文章注明出处:https://www.cnblogs.com/zhaohongcheng/</h3>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/zhaohongcheng/p/10839412.html
頁: [1]
查看完整版本: 新手怎么学JS?JavaScript基础入门