JavaScript 从入门到丢弃 - 2 - 类型/值/变量

词法结构

  • 字符集:unicode

  • 分别轻重缓急写,关键字、变量、函数名、标示符必须使用大小写一致

  • 注释

    // 单行注释
    /* ~一段注释~ */ // 另一段注释
    /*
     * 多行注释
     * 多行注释
    */
    
  • 直接量

    12  // 数字
    1.2 // 小数
    "hello world" // 一个字符串
    'hi'  // 另一种字符串
    true  // 布尔值
    /^javascript$/gi //正则表达式直接量
    null // 空
    {  x:1 ,y:2}  // 对象
    [ 1,2,3,4,5 ] //数组
    
  • 标示符、保留字

  • 可选的分公司

    1. 在此外索要分割的地点选择 ; 举办分隔
    2. 在此外可以概括分号的地点都将其简单

    一经不拔取分号,由于语句的相间规则,会造成一些出乎意料的气象,提议无论怎么着时候都利用分号举办分割

浮点型间接量

浮点型采纳传统实数写法,可以应用指数计数法和更精简的记法

  • 3.14
  • 7.03E-12
  • .3333333

形式匹配

js定义了RegExp()函数,用来创制文本匹配模式的对象,称为正则表明式

RegExp不是js的主旨数据类型,和Date一样,只是一种具有实用API的特种目的,可是依然有着间接量写法,
可以从来在js中选拔,在两条斜线之间的文件构成正则表明式间接量。第二条斜线之后也足以跟随一个或多少个字母,
用来修饰匹配格局含义

/^HTML/ //匹配以HTML开始的字符串
/[1-9][0-9]*/ // 匹配一个非零数字,后面是任意个数字
/\bjavascript\b/i // 匹配单词“javascript”,忽略大小写

RegExp对象定义有用的方法,字符串也有接收RegExp参数的法子

var text = 'testing: 1, 2, 3';  
var pattern = /\d+/g // 匹配所有包含一个或多个数字的实例
pattern.test(text)  // true 匹配成功
text.serch(pattern) // 9,首次匹配成功的位置
text.match(pattern) // ["1","2","3"] 所有匹配组成的数组
text.replace(pattern,"#") //"testing,#, #, #"
text.split(/\D+/) //["","1","2","3"] 用非数字截取字符串

全局对象

全局对象在js中拥有举足轻重用途,全局对象属性是大局定义的记号,js程序可以一向动用
js解释器启动时,会创设一个的新的全局对象,并定义初阶属性:

  • 全局属性,比如undefined、Infinity和NaN
  • 大局函数,比如isNaN(),parseInt()和eval()
  • 构造函数,比如Date(),RegExp(),String(),Object()和Array()
  • 全局对象,比如Math和JSON

大局对象的初阶属性并不是保留字,然则应当作为保留字对待,还有Windows对象定义一些外加的全局属性,也应该保留

var global = this; // 定义一个引用的全局对象的全局变量

二进制浮点数和四舍五入错误

js可以准确的表示分数,比如1/2、1/8,但无法准确表示0.1这样数字

var x = .3 - .2;
var y = .2 - .1;
x == y; // => false 两个值不相等
x == .1 // => false ,0.3 - 0.2 不等于 0.1
y == .1 // => true, 0.2 - 0.1 等于 0.1

算术运算

运算符辅助:+,-,*,/,%

js还帮忙更加复杂的算术运算,通过作为Math对象的特性定义的函数和常量来促成

Math.pow(2,53)  // 2的53次幂
Math.round(.6)  // => 1.0 四舍五入
Math.ceil(.6)   // => 1.0 向上求整
Math.floor(.6)  // => 0.0 向下求整
Math.abs(-4)    // 绝对值
Math.max(x,y,z) // 返回最大值
Math.min(x,y,z) // 返回最小值
Math.random()   // 生成一个0-1.0的随机数
Math.PI         // 圆周率
Math.E          // e,自然对数
Math.sqrt(3)    // 3的平方根
Math.sin(0)     // 三角函数
Math.log(10)    // 10的自然对数
Math.log(100)/Math.LN10   // 以10为底的对数
Math.log(512)/Math.LN2    // 以2为底的对数
Math.exp(3)     // e的3次幂

正无穷大:Infinity
非数字值: NaN

Infinity                  // 将一个可读可写的变量初始化为Infinity
Number.POSITIVE_INFINITY  // Infinity,只读
1/0                       // Infinity
Number.MAX_VALUE + 1      // Infinity
Number.NEGTIVE_INFINITY   // 负无穷大
-Infinity                 // 负无穷大
-1/0                      // 负无穷大
-Number.MAX_VALUE - 1     // 将一个可读可写变量初始化为NaN
NaN                       // 非数字值
Number.NaN                // 非数字值,只读
0/0                       // NaN
Number.MIN_VALUE/2        // 下溢,计算结果为0
-Number.MIN_VALUE/2       // 负零
-1/Infinity               // 负零
-0                        // 负零,下溢,比js所能表示的0还小时,计算结果为0

负零和正零是相等的,除了作为除数之外

var zero = 0;
var negz = -0;
zero === negz;    // => true
1/zero === 1/negz // => false

不可变的原始值和可变的靶子引用

js
中华始值(undefined,null,布尔值,数字ECMAScript,,字符串)与目标(包括数组和函数)有着根本区别。

  • 原始值时不足更改的,任何情势都没法儿更改(或者突变)一个原始值

对数字和布尔值来说肯定那样-改变数字值本身就说不通,对字符串来说不是很强烈。
字符串是由字符组成数组,我们盼望经过指定索引来修改字符串中的字符。实际上js禁止这样的行事,
字符串方法看起来重回修改后的字符串,实际上是回去新的字符串值
比如:

var s = "hello"; // 创建一个小写组成的字符串
s.toUpperCase(); // 返回"HELLO",但是没有改变s的值
s                // s=“hello”,s原字符串并没有改变
  • 原始值的相比较只是值的可比

原始值唯有在值相等时才约等于,对于数字、布尔值、null和undefined来说相比较容易明白,对于字符串则不了解了
单独相比2个字符串,只有2个字符串长度相等且每个索引的字符都等于,才是相等

  • 目的是可变的,值是可修改的

栗子:

var o = { x:1 }; // 定义一个对象
o.x = 2;         // 修改对象属性值来修改对象
0.y = 3;         // 再次修改对象,增加一个属性-y
var a = [1,2,3]  // 数组也是可修改的
a[0] = 0;        // 更改数组的一个元素
a[3] = 4;        // 给数组增加一个新元素
  • 对象的相比不是值的可比,而是对象引用的可比

就是2个对象涵盖同样的性质和相同值,也不是相等的
逐一索引元素完全相等的多个数组也不等于。

var o = { x:1 }, p = { x:1 } // 具有同样属性和值的两个对象
0 === p // false ,两个单独的对象永远不相等
var a = [], b =[]  // 两个单独的空数组
a === b // false 两个单独的数组永远不相等

普普通通讲,对象被称作引用类型,以便将js基本项目区分。对象值都是引用,对象的可比都是引用的比较
当且仅当她们援引同一个目的时,才会等于

var a = []; // 定义一个空的数组
var b = a; // 变量b引用a
b[0] = 1; // 通过b的引用修改a
a[0];  // 1,a的值也修改了
a === b; // true,a和b引用同一个数组,相等

如上所示,将目标或数组赋值给一个变量,仅仅是赋值的引用值:对象自我并未被复制两回

倘诺想取得一个目的或者数组的副本,必须出示复制对象每一个属性或数组每一个因素

譬如说循环来完成数组复制:

var a = [1,2,3];
var b = [];
for(var i = 0; i < a.length; i++){
  b[i] = a[i];
}

如出一辙的,假若想相比较2个单身的对象或者数组,必须相比全部的习性或者元素
正如2个数组的函数:

function equalArrays(a,b){
  if ( a.lengh != b.length) return false;
  for(var i=0; i<a.length; i++ ){
    if(a[i] !== b[i]) return false;
  }
  return true;
}

展现类型转换

为了使代码更加清晰明了,平日利用突显转换,最简单易行的不二法门就是不利用new运算符来调用Boolean()、Number()、
String(),Object()函数

Number("3") // '3'=>3
String(false) // false => "false"
Boolean([]) // => true
Object(3) // => new Number(3)

除去null和undefined以外都有toString方法,一般实施结果与String()重返结果一致

假定准备把null 和 undefined
转换为对象,会抛出一个档次错误。假诺应用object()则不会抛出非常,仅仅
简单的回来一个新创立的空对象

js中一些运算符会做隐式的类型转换

  • +运算符

一个操作数是数字,另一个操作数是字符串,则会把非字符串的操作数转换成字符串然后拼接之后回到(非字符串操作数不会改变类型)
1+'1' // => '11'(String)
x + '' // => 等价于String(x)

  • !运算符

会把操作数转换为布尔值并取反。(操作数不会变动类型)
!!x // 等价于Boolean(x)

Number => String

  • Number类定义的toString()方法可以承受代表转换基数的可选参数,假若不点名,则转移基于十进制

var n = 17;
binary_string = n.toString(2);
octal_string = "0" + n.toString(8);
hex_string = "0X" + n.toString(16);
  • 决定小数点地点和行之有效数字位数
  1. toFixed() 依据小数点后指定位数将数字转换为字符串,从不使用指数计数法
  2. toExponential() 依据指数记数法将数字转换为指定形式字符串
  3. toPrecision()按照指定的有效位数将数字转换为字符串。倘诺可行数字的位数少于数字整数局部位数,转换成指数形式

var n = 123456.789;
n.toFixed(0); // '123457'
n.toFixed(2); // '123456.79'
n.toFixed(5); // '123456.78900'
n.toExponential(1); // '1.2e+5'
n.toExponential(3); // '1.235e+5'
n.toPrecision(4); // '1.235e+5'
n.toPrecision(7); // '123456.8'
n.toPrecision(10); // '123456.7890'

String => Number

  • Number()接受传入一个字符串,试图将其更换为一个平头还是浮点数直接量,基于十进制数转换,且无法带非法字符
  • parseInt() 只分析整数,并且能够由此字符串前缀“0X”或”0x”
    解析为16进制数
  • parseFloat 解析浮点数和整数

parseInt("3 asd"); // => 3
parseInt("3.124"); // => 3
parseInt("0xff"); // => 255
parseInt("-0x7f"); // => -127

parseFloat("3.14 asdas") // => 3.14
parseFloat(".1") // => 0.1

parseInt(".1") // => NaN 整数不能以`.`开始
parseFloat("$111.11") // => NaN 数字不能以"$"开始

parseInt 可以吸收第二个可选参数,指定数字转换的基数,合法范围 2~36

parseInt("11",2); // => 3
parseInt("ff",16); // => 255
parseInt("zz",36); // => 1295
parseInt("077",8); // => 63
parseInt("077",10); // => 77

对象转换为原始值

  • Object => Boolean

怀有目标(包括数组和函数)都更换为true

  • Object => String

toString()
valueOf()

  • Object => Number

valueOf()
toString()

js的目的到字符串转换步骤:

  • 假定目的有toString方法,则调用这么些办法。假使回去一个原始值,则js将以此值转换为字符串,再次回到字符串结果
  • 万一目的没有toString方法,或者这些方法不回来原始值,则调用valueOf方法。假若存在这么些办法,则js
    调用。假如回到时原始值,js将以此值转换为字符串,然后回到字符串结果
  • 倘诺没有上述两个章程,或者以上2个措施重返的不是原始值,会抛出一个门类错误极度

js的靶子到数字转换过程:
js转换数字过程与字符串过程差不多,只是优先采纳valueOf

  • 假若目的有valueOf方法,则调用这么些办法。倘若回到一个原始值,则js将以此值转换为字符串,重返字符串结果
  • 一旦目标没有valueOf方法,或者那么些办法不回来原始值,则调用toString方法。假如存在这多少个主意,则js
    调用。假设回去时原始值,js将以此值转换为字符串,然后回到字符串结果
  • 假使没有上述多少个模式,或者以上2个方法重临的不是原始值,会抛出一个类型错误非凡

何以空数组和单个数字数组会被更换成0和单个数字?

  • 数组继承了Object默认的valueOf方法,再次来到一个目标而不是原始值,因而调用toString()方法,这么些法子重临一个原始值
    为此数组到数字的转换为空字符串,空字符串转换成数字0
  • 含蓄一个元素的数组转换成字符串结果和单个元素转换字符串的结果一致。转换成单个数字的字符串,然后转换成数字

“+”运算符的一个数字,一个操作数是目的,意况咋样?
js将运用“特殊情势”将目标转换成原始值,而不是此外运算符的情势执行对象到数字的变换,“==”运算符与此类似。
固然将目标和原始值相比较,则转换会将对象到原始值的转换情势开展

“+”、“==”应用在目的到原始值的变换特殊意况
只要涉及到日期对象,而日期类是js中绝无仅有的预先定义类型,定义了有意义的向字符串和数字的转移。
对此有所非日期对象,对象到原始值的转移基本上是目的到数字的更换,也就是首先调用valueOf。
对此日期对象,则利用对象到字符串的变换形式,通过valueOf或toString重临的原始值被直接使用,而不会被威吓转换为数字或字符串,与其他的更换有部分不同

“<“运算符
享有涉及运算符对对象做靶子到原始值的变换,但要出去日期对象情形。任何对象都好第一尝试调用valueOf,然后调用toString。
无论是得到的原始值能否被直接使用,都不会越加转换为数字或字符串。

“+” “==” “!=”
和事关运算符是唯一进行那种奇异的字符串到原始值的转移模式的运算符

任何运算符到特定类型的更换都很显眼,而且对日期对象来讲,也一贯不万分情形

var now = new Date();
typeof(now + 1); // "string","+"将日期转换为字符串
typeof(now - 1); // "number" ,"-" 将使用对象到数字的转换
now == now.toString(); // true ,隐式的和显式的字符串转换
now > (now - 1); // true,">"将日期转换为数字

转换和相等性

js可以做灵活的类型转换,相等运算符也跟相等的意思一样,灵活多变
下面的可比结实都是true:

null == undefined; // 这两个值被认为相等
"0" == 0;   // 比较之前,字符串转换成数字
0 == false; //  比较之前,布尔值转换成数字
"0" == false; // 比较之前字符串和布尔值都转换成数字

需要留意,一个值转换成另一个值不代表两个值分外。

假设在盼望利用布尔值的地点接纳undefined,会变换成false,但不代表undefined
== false

js中,if语句将undefined转换成false,但
==运算符不会统计将操作数转换为布尔值

字符串使用

jsn 内置功效之一就是字符串连接,将+用来字符串,则意味着字符串连接
msg = "Hello" + " " + "World"

赢得字符串长度: s.length

除去length属性,还提供成千上万调用方法:

var s = "hello,wolrd"
s.charAt(0)             // "h":第一个字符
s.charAt(s.length-1)    // "d":最后一个字符
s.substring(1,4)        // "ell": 第2-4个字符
s.slice(1,4)            // "ell": 第2-4个字符
s.slice(-3)             // "rld": 最后三个字符
s.indexOf("l")          // 2: l 首次出现的位置
s.lastIndexOf('l')      // 10: l最后出现的位置
s.indexOf('l',3)        // 3:  在位置3之后首次出现l的位置
s.split(",")            // ["hello","world"] 分割成字符串
s.replace('h','H')      // "Hello,world",将h替换成H
s.toUpperCase()         // "HELLO,WORLD",转成大写字符串

类型转换

转换为字符串 数字 布尔值 对象
undefined "undefined" NaN false throws TypeError
null "null" 0 false throw TypeError
true "true" 1 XXXXXXX new Boolean(true)
false "false" 0 XXXXXXX new Boolean(false)
""(空字符串) XXXXXXX 0 false new String("")
"1.2" XXXXXXX 1.2 true new String("1.2")
"one" XXXXXXX NaN true new String("one")
0 "0" XXXXXXX false new Number(0)
-0 "0" XXXXXXX false new Number(-0)
NaN "NaN" XXXXXXX false new Number(NaN)
Infinity "Infinity" XXXXXXX true new Number(Infinity)
-Infinity "-Infinity" XXXXXXX true new Number(-Infinity)
1(无穷大,非零) "1" XXXXXXX true new Number(1)
{} 复杂 复杂 true XXXXXXX
[] "" 0 true XXXXXXX
[9] “9” 9 true XXXXXXX
[‘a’] 使用join()方法 NaN true XXXXXXX
function(){} 复杂 NaN true XXXXXXX

原始值到目的的转移也很简单,原始值调用String(),Number(),Boolean()构造函数,转换为各自的包装对象

null 和
undefined属于不同,当做是一个对象的地方都会暴发一个门类错误分外,不会举行健康类型转换

变量效能域

全局变量拥有全局成效域

函数内注脚的变量和函数参数都是部分变量,只好在函数体内有定义

函数体内,局部变量优先级高于全局变量,同名局部变量覆盖全局变量

var scope = "global"; 
function check() {
  var scope = "local";
  return scope; // 返回"local"
}
a = check(); // => "local"

变量声明

js中通过var重在字来声称一个变量

var a = 1;
var a,b;
var i=0,j=1,k=2;

如若未在var语句中,就给变量指定最先值,那么即便声称那些变量,不过给它存入一个值前,先导值是undefined

重新注脚一个变量合法,且从未此外伤害

数字

用作性能的变量

js的全局变量,其实是概念了大局对象的一个性能。
当使用var注解一个变量,创立的那些特性是不得以安排的。无法通过delete删除
假定给一个未注解的变量赋值,js会自动创制一个全局变量,是大局对象的健康可配备的性能,可以通过delete删除

var some = 1;
gvar = 1;
delete some; // => false,变量没被删除
delete gvar; // => true,变量被删除

null和undefined

null: 描述”空值”
undefined: 未定义的值,讲明变量没有开始化

虽然null和undefined不同,可是都表示值的空缺,往往可以互换
null == undefined // => true

null和undefined 都不包含其他性质和方法

string (文本)

js是接纳UTF-16编码的Unicode字符集,string是由一组16位值组成的
不可变 的不变系列,每个字符
一般来自于Unicode字符集。
js通过字符串类型来表示文本。字符串的长短是其所含的16位值的个数。
js字符串的目录从0先河,空字符串长度为0

js字符串直接量是由单引号或者双引号括起来的字符体系。

""
'test'
"3.14"
'name="myform"'
"Would't you prefer to say goobye?"
"this string\nhas two lines"

在ECMAScript3中,字符串直接量必须写在一行,而在ECMAScript5中,字符串直接量可以拆成数行,每一行
透过反斜线(\\)截止,反斜线和行终止符都不算字符串直接量的始末

"two\nlines"

"one\
two\
three"

布尔值

布尔值:truefalse

正如语句结果通常是布尔值,a==4

任意js值都可以变换为布尔值,下边转换成false:

undefined
null
0
-0
NaN
"" // 空字符串

拥有其他值,包括富有目的数组,都会转换成true

检测o是否是非null值,只有o不是null时才会履行if后边代码
if( o !== null)...

o不是其他假值才会履行if前面代码:
if( o)...

布尔值包含toString(),可以将字符串转换为"true""false"

布尔值运算符:&&(与) 、 ||(或) 、 (非)

包装对象

js 对象是一种复合值,属性或已命名的汇集。
通过.标志来引用属性值
当属性值是一个方法时,称其为艺术。通过O.m()来调用对象O中的方法

字符串同样有着属性和艺术:

var s = "hello world!";
var word = s.substring(s.indexOf(' ')+1, s.length); // word="world!"

字符串既然不是目的,为什么有性能呢?
因为引用了字符串s的特性,js会将字符串值通过调用new String(s)的艺术转换成对象,这多少个目的继承了
字符串的办法,并被用来拍卖属性的引用。一但引用停止,这一个新创设对象便被灭绝了

同字符串一样,数字和布尔值也颇具各自的艺术:通过Number()Boolean构造函数创造一个临时对象,
这个措施的调用均来自这么些临时对象。

null和undefined没有包装对象,访问他们的性能,会造成一个档次错误

看个栗子,思考一下实施结果:

var s = "test"; // 创建一个字符串
s.len = 4;      // 给s设置一个属性值,创建一个临时字符串对象,并且赋值len=4,然后销毁这个临时对象
var t = s.len;  // 查询这个属性,通过原始的(没有修改过的)字符串值创建一个新的字符串对象,尝试读取len,属性不存在,t为undefined

存取字符串、数字、布尔值的性质时暂时创办的目标叫做 打包对象

装进对象只是被当作一种实现细节,不需要特地关心。由于字符串、数字、和布尔值的特性都是只读的,
再者不可能定义新属性,与目的是有分此外

留意,可以经过String() Number()
Boolean()构造函数显式制造包装对象:

var s = "test", n = 1, b = true;  // 一个字符串、数字、布尔值
var S = new String(s);  // 一个字符串对象
var N = new Number(n);  // 一个数字对象
var B = new Boolean(b); // 一个布尔值对象

js
会在必要时包装对象转换成原始值,由此上段代码中对象S、N、B经常,但不连续表现和值s、n、b一样。
==将原始值和其包装对象就是相等
===将它们就是不对等,通过typeof运算符可以看出原始值和包装对象的例外

连串、值和变量

js中的数据类型:

  • 数字
  • 字符串
  • 布尔值
  • null
  • undefine
  • 对象

js数据类型分为2类:原始类型对象类型

原始类型:

  • 数字
  • 字符串
  • 布尔值
  • 奇异的原始值:‘null’ 和 ‘undefine’

目标类型:

  • 性能的集合
  • 数组
  • 函数

日期和时间

js语言核心包括Date()构造函数,用来代表日期和岁月

var then = new Date(2016.4.22); // 2016年4月22日
var later = new Date(2016,3,25,17,19,30) // 2016.4.25 17:19:30pm
var now = new Date(); // 当前时间和日期
var elapsed = now - then; // 日期减法,计算当前时间间隔的毫秒数
later.getFullYear(); //  => 2016
later.getMonth(); // => 3 ,月份从0开始
later.getDate() // => 25,从1开始的天数
later.getDay() // =>  1,星期几,0代表星期日,1代表星期1
later.getHours() // => 17 当地时间17:19pm
later.getUTCHours() // => 9 我所在UTC-8 使用UTC表示小时的时间,基于时区,所以返回9

声明提前

js的函数功能域指的是,在函数内阐明的保有变量,在函数体内始终可以看到,变量在阐明在此之前仍然早已得以使用,这多少个特性称为“声明提前”

看下下边一段代码,你或许会以为首先个打印”global”,因为代码没有实施到var语句。其实,局部变量在函数体内始终有定义,也就是说,
函数体内部分变量覆盖同名全局变量。不过只有进行到var语句时部分变量才会赋值,由此,下边的实践进程相当于,将函数变量表明
“提前”函数体顶部,同时开首化地方如故留在原来职位

var scope = "global";
function check() {
  console.log(scope);  // "undefined"
  var scope = "local"; // 赋初始值
  console.log(scope); // “local”
}

整型直接量

js不区分整数值和浮点数值,所有的数字均用浮点数值表示。js拔取的时IEEE
754定义的64位浮点格式来表示数字,
下一场需要留意,js中实际的操作(比如数组索引)则是基于32位整数的

支撑的整型直接量

  • 十进制 1000
  • 十六进制 0x1F、0X39

有些ECMAScript实现是协理八进制的,但ECMAScript标准不扶助八进制直接量,在ECMAScript6的严刻情势下,八进制是禁止的

转义字符

在js中,反斜线有很是用途,用来开展转义,不是原本的趣味了

转义字符 含义
\o NUL字符(\u0000)
\b 退格符(\u0008)
\t 水平制表符
\n 换行符(\u000A)
\v 垂直制表符(\u000B)
\f 换页符(\u000C)
\r 回车符(\u000D)
" 双引号(\u0022)
单引号(\u0027)
\ 反斜线(\u005C)
\XXXXXXXX 两位16进制XXXXXXX指定的Latin-1字符
\uXXXXXXXXXXXXXX 4位十六进制XXXXXXXXXXXXXX指定的Unicode字符