JS 类型和语法1
JavaScript类型
Javascript有七种内置类型:
- 空值(null)
- 未定义(undefined)
- 布尔值(boolean)
- 数字(number)
- 字符串(string)
- 对象(object)
- 符号(symbol, ES6 新增)
我们可以用 typeof 运算符来查看值的类型,它返回的是类型的字符串值。但是其中类型和他们的字符串值并不一一对应:
其中 typeof null === “object” // true 比较特殊,我们需要使用符合条件来检测 null 值的类型:
var a = null;
(!a && typeof a === "object");
null 是“假值”(falsy 或者 false-like),也是唯一一个用typeof 检测会返回“object”的基本类型值。
还有一种情况:
typeof function a(){} === "function";
这样看来,function 也是 JavaScript 的一个内置类型。然而,它实际上只是 object 的一个“子类型”。具体来说,函数是“可调用对象”,它有一个内部属性[[ call ]] ,该属性使其可以被调用。
函数不仅仅是对象,还可以拥有属性。例如:
function a(b, c) {
}
函数对象的 length 属性是其声明的参数的个数:
a.length; //2
因为该函数声明了两个命名函数,b 和 c,所以其 length 值为 2。
再来看看数组。Javascript 支持数组,那么它是否也是一个特殊类型?
typeof [1, 2, 3] === "object";
值和类型
JavaScript 中的变量是没有类型的,只有值才有。变量可以随时持有任何类型的值。
换句话说,就是 js 的变量在声明一个变量的时候不需要强调它的类型,同时同一变量可以是多种类型的值。比如一个变量可以现在被赋值为字符串类型,随后又被赋值为数字类型值。
undefined 和 undeclared
已在作用域中声明但还没有赋值的变量,是undefinded。还没有在作用域中声明过的变量是 undeclared。
var a;
a;
b;
typeof a;
typeof b;
值
1.数组
和其他强类型语言不同,在 Javascript 中,数组可以容纳任何类型的值,可以是字符串、数字、对象,甚至其他数组(多维数组就是通过这种方式实现的)。
…
可以通过 slice() 来将类数组转化为数组。
Array.prototype.slice.call( arguments );
slice() 返回参数列表。Array.form 同样可以实现这个功能。
数组常用的方法有:
- push() 添加元素到数组末尾
- pop() 删除数组末尾元素
- shift() 删除数组最前面的元素
- unshift() 添加元素到数组的头部
- indexOf() 查看某个某个元素在数组中的位置,存在就是当前下标,如果不存在就为-1;
- splice 是数组中最强大的功能之一,增,删,改
- slice 不会改变原数组,获取数组元素,不加参数为浅拷贝
- Array.from() 方法从一个类似数组或可迭代对象中创建一个新的数组实例。
- Array.isArray() 用于确定传递的值是否是一个 Array。
- Array.of() 方法创建一个具有可变数量参数的新数组实例
- concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
- array.copyWithin(target, start, end) 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,而不修改其大小。
- entries() 方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。
- keys() 方法返回一个新的Array迭代器,它包含数组中每个索引的键。 返回的是下标
- values() 方法返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值。
- every() 方法测试数组的所有元素是否都通过了指定函数的测试。
- some() 方法测试数组中的某些元素是否通过由提供的函数实现的测试。
- fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。
- filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
- find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
- findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。
- forEach() 方法对数组的每个元素执行一次提供的函数。 //item是值,index下标,array是原数组
- includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回
- indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
- join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。
- reduce() 方法对累加器和数组中的每个元素(从左到右)应用一个函数,将其减少为单个值。
- reverse() 方法将数组中元素的位置颠倒。
字符串
字符串拥有和数组一些相似的地方,比如通过 a[0] 这样的索引来访问元素。indexOf 来查找元素下标。concat() 来合并。但是并不意味着字符串就是字符数组。
Javascript中字符串是不可变的,而数组是可变的。字符串的成员函数不会改变其原始值,而是创建并返回一个新的字符串。而数组的成员函数都是在其原始值上进行操作。
许多数组函数用来处理字符串很方便。虽然字符串没有这些函数。但是可以借用:
var a = "foo";
a.join;
a.map;
var c = Array.prototype.join.call(a, "-");
var d = Array.prototype.map.call(a, function(v) { } );
这样既可以调用了。
字符串反转可以通过则无法借用,因为反转是会改变成员对象的,而字符串是不可变的。不过我们可以通过以下操作来进行反转:
var c = a.split("").reverse().join("")
字符串常用的方法有:
charAt() 返回指定索引位置处的字符slice() 提取字符串的片断,并把提取的字符串作为新的字符串返回出来split() 使用指定的分隔符将一个字符串拆分为多个子字符串,并将其以数组形式返回。substr(), substring() 截取一个字符串的片段,并返回截取的字符串。 substr和substring这两个方法不同的地方就在于参数二,substr的参数二是截取返回出来的这个字符串指定的长度,substring的参数二是截取返回这个字符串的结束点,并且不包含这个结束点。match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配,并返回一个包含该搜索结果的数组。replace() 把一个目标字符串当中的文本,替换成自己需要的字符。search() 在目标字符串中搜索与正则规则相匹配的字符,搜索到,则返回第一个匹配项在目标字符串当中的位置,没有搜索到则返回一个-1。toLowerCase(),toUpperCase() 全部转为大写或小写includes(), startsWith(), endsWith() includes用来检测目标字符串对象是否包含某个字符,返回一个布尔值,startsWith用来检测当前字符是否是目标字符串的起始部分,相对的endwith是用来检测是否是目标字符串的结尾部分。repeat() 返回一个新的字符串对象,新字符串等于重复了指定次数的原始字符串。接收一个参数,就是指定重复的次数。
Nubmer
Javascript 只有一种数值类型:number,包括“整数”和带小数的十进制数。
JavaScript中的整数就是没有小数的十进制数。所以 42.0 等同于 42。
JavaScript 中的数字类型是基于 IEEE 754 标准来实现的,该标准通常也被称为“浮点数”。JavaScript 使用的是“双精度”格式(即64位二进制)。
默认情况下大部分数字都以十进制显示,小数部分最后面的 0 被省略。特别大和特别小的数字默认使用指数格式显示。
tofixed(…) 方法可以指定小数部分的显示位数。 toPrecision(…) 方法用来指定有效位数 的显示位数,(可以四舍五入)。
特殊数值
undefined 指没有值或从未赋值,null 表示空值或曾赋过值但目前没有值。
null 是一个特殊关键字,不是标识符,我们不能将其当作变量来使用和赋值。然而 undefined 却是一个标识符,可以被当作变量来使用和赋值。
void 是一个运算符。void __ 没有返回值,因此返回结果是 undefined。void 不改变表达式的结果,只是让表达式不返回值。
NaN 意指“不是一个数字”“not a number”。可以理解为“无效数值”。
例如:
var a = 2 / "foo"; // NaN
NaN 不等于自身
JavaScript有一个常规的0(也叫+0)和一个 -0。
var a = 0 / 3; // -0
var a = 0 * 3; // -0
+0 === -0 // true
加法和减法不会得到 -0。
我们为什么需要-0 呢?有些应用程序中的数据需要以级数形式来表示(比如动画帧的移动速度),数字的符号位用来代表其他信息(比如移动方向)。此时如果一个值为 0 的变量失去了它的符号位,它的方向信息就会丢失。所以保留 0 值的符号位可以防止这类情况的发生。
ES6 新加入 object.is 判断两个值是否绝对相等。对于ES6 之前的版本,有一个简单的 polyfill:
if(!Object.is) {
Object.is = function(v1, v2) {
if((v1 === 0 && v2 === 0)) {
return 1 / v1 === 1 / v2;
}
if(v1 !== v1) {
return v2 !== v2;
}
return v1 === v2
}
}
值和引用
JavaScript中没有指针,JavaScript 中变量不可能成为指向另一个变量的指向另一个变量的引用。JavaScript 引用指向的是值。
JavaScript 对值和引用的赋值/传递在语法上没有区别,完全根据值的类型来决定。
下面看一个例子:
function foo(x) {
x.push(4);
x;
x = [4,5,6];
x.push(7);
x;
}
var a = [1,2,3]
foo(a);
a;
在向函数传递a 的时候,实际是将引用 a 的一个复本赋值给 x,而a 仍然指向 [1,2,3]。在函数中我们可以通过引用 x 来更改数组的值,但并不影响 a 的指向,所以a 仍然指向 [1,2,3,4]。
再看一个例子:
function foo(x) {
x = x + 1;
x;
}
var a = 2;
var b = new Number(a);
foo(b);
console.log(b);
原因是标量是基本类型值是不可变的。如果一个数字对象的基本类型值是2,那么该值就不能更改,除非创建一个包含新值的数字对象。
x = x + 1,x 的标量基本类型值 2 从数字对象中拆封出来后,x就神不知鬼不觉地从引用对象变成了数字值,它的值 2 + 1 = 3.然而函数外的 b 仍然指向原来那个值为 2 的数字对象。
我们可以为数字对象添加属性,通过它们间接地进行数据交换。
本文所有用例,部分话语引用自 “You Don’t Know JavaScript: Types & Grammar by Kyle Simpson(O’Reilly).Copyright 2015 Getify Solutions, Inx., 978-1-491-909419-0”
|