赞
踩
代码,是前端工程师的“武器”,也是他们的“面包和黄油”。
ECMAScript 标准定义了原始数据类型和引用数据类型,共七种内置类型:
原始数据类型(基本类型):按值访问,可以操作保存在变量中实际的值。
引用类型(复杂数据类型):引用类型的值是保存在内存中的对象。
⚠️ 注意:与其他语言不同的是,JavaScript 不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。所以引用类型的值是按引用访问的。
Null 类型只有一个唯一的字面值 null,表示一个指针对象,这也是在使用 typeof 运算符检测 null 值时会返回“object”的原因。
在定义将来要保存对象值的变量时,建议使用 null 来初始化,不要使用其他值。原因:只要检查这个变量的值是不是 null 就可以知道这个变量是否在后来被重新赋予了一个对象的引用。
null 是表示缺少的标识,指示变量未指向任何对象。把 null 作为尚未创建的对象,也许更好理解。
常见出现 null 的场景:
let returnObj = null;
function foo(){
return {
name: 'king'
};
}
returnObj = foo();
document.querySelector('#id'); // null
'test'.match(/a/); // null
Undefined 类型只有一个唯一的字面值 undefined,表示的是一个变量不存在。任何变量在赋值前都是 Undefined 类型、值为 undefined。同时也是全局对象的一个属性(window.undefined)。
常见出现 undefined 的场景:
var foo;
console.log(foo); // undefined
var obj = {
name: "king"
};
console.log(obj.address) // undefined
function foo(){}
console.log(foo()); // undefined
function foo(param1, param2, param3){
console.log(param3);
}
foo(1, 2) // undefined
布尔类型表示一个逻辑实体,可以有两个值:true 和 false
如果变量不是 Boolean 类型的值,那么JavaScript 解释器会自动调用 Boolean() 函数对变量进行类型转换,返回最终符合 if 语句判断的 true 或者 false 值。
new Boolean()
null、undefined、false、0、-0、NaN、"" // false
true、"false"、Object、{}、Array、[] 、Function // true
decimals-小数
intergers-整数
进制数
// 八进制的56
var num2 = 070;
// 十进制
var num1 = 10;
// 十进制,因为有数字超过了7,这里是79
var num3 = 079;
// 十六进制的31
var num4 = 0x1f;
// 进制转换(带参数)
Number.toString(2/8/16)
⚠️ 注意: 八进制在严格模式下 “use strict” 是无效的,会导致 JavaScript 报错,避免使用。
浮点数-Float
var num = 0.1 + 0.2;
var sum = '2.3' * 100;
console.log(num);
// 0.30000000000000000004
console.log(sum);
// 229.99999999999997
上面例子表达的就是 JavaScript 的浮点型数据在计算时容易丢失精度,这一点并不仅在 JavaScript 存在,建议处理这方面问题使用专用的数字处理类,比如 Java 里的 BigDecima 类来处理。
双精度
双精度是一种特定类型的浮点数,它们具有比标准浮点数更高的精度(这意味着它们精确到更大的小数位数)。
Infinity - 数字的范围
JavaScript 中数值的范围是有效位数的,基本上够我们使用,我们仅需要知道以下几个知识点:
NaN 属于 JavaScript 保留词,指示某个数不是合法数,用于表述本来要返回数值的操作失败了(而不是抛出错误)
let x = 100 / "Apple"; // x 将是 NaN(Not a Number)
// 不过,假如字符串包含数值,则结果将是数:
let x = 100 / "10"; // x 将是 10
NaN (Not a number)的含义是本该返回数值的操作未返回数值,返回了 NaN 就不会抛出异常影响语句流畅性。
NaN 属性的初始值就是 NaN,和 Number.NaN 的值一样。
在现代浏览器中(ES5 环境), NaN 属性是一个不可配置(non-configurable)、不可写(non-writable)的属性。但在 ES3 中,这个属性的值是可以被更改的,但是也应该避免覆盖。
编码中很少直接使用到 NaN。通常都是在计算失败时,作为 Math 的某个方法的返回值出现的(例如:Math.sqrt(-1))或者尝试将一个字符串解析成数字但失败了的时候(例如:parseInt(“blabla”))。
类型转换
Nmuber() 函数
1-Boolean 类型 true => 1 false => 0 2- Null 类型 null => 0 3- Unedfined 类型 undefined => NaN 4- String 类型 只包含数字 => 十进制数 只包含有效的浮点数 => 十进制数 包含有效的十六进制数 => 十六进制数 空字符串 => 0 包含除以上格式以外而定字符串 => NaN 5- Object 类型 先调用 valueOf()函数—返回值按照以上规则,如果结果是NaN,则调用 toString()函数
常见应用
let x = 999999999999999; // x 将是 999999999999999
let y = 9999999999999999; // y 将是 10000000000000000 被四舍五入
let x = 0.2 + 0.1; // x 将是 0.30000000000000004
let x = 10, y = "20";
let z = x + y; // z 将是 1020(一个字符串)
let x = 10, y = 20, z = "30";
let result = x + y + z; // 3030
JavaScript 从左向右进行编译。因为 x 和 y 都是数,10 + 20 将被相加。因为 z 是字符串,30 + “30” 被级联。
4. 数字字符串
在所有数字运算中,JavaScript 会尝试将字符串转换为数字:
let x = "100", y = "10";
let z = x / y; // z 将是 10
let x = "100", y = "10";
let z = x - y; // z 将是 90
let x = "100", y = "10";
let z = x + y; // z 不会是 110(而是 10010)
浮点数计算
JavaScript 的字符串类型用于表示文本数据。它是一组 16 位的无符号整数值的元素。在字符串中的每个元素占据了字符串的位置。第一个元素的索引为 0,下一个是索引 1,依此类推。字符串的长度是它的元素的数量。
'foo';
'bar';
'1234';
'one line \n another line';
"John's cat";
符号(Symbols)是 ECMAScript 第 6 版新定义的数据类型。符号是原始值,且符合实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。
let genericSymbol = Symbol();
let otherGenericSymbol = Symbol();
let fooSymbol = Symbol('foo');
let otherFooSymbol = Symbol('foo');
console.log(genericSymbol == otherGenericSymbol ) // false
console.log(fooSymbol == otherFooSymbol) // false
该类型的性质在于这个类型的值可以用来创建匿名的对象属性。该数据类型通常被用作一个对象属性的键值,当这个属性是用于类或对象类型的内部使用的时候。
var myPrivateMethod = Symbol();
this[myPrivateMethod] = function () {
// ...
};
let s1 = Symbol('foo'),
s2 = Symbol('bar');
let o = {
[s1]: 'foo val',
[s2]: 'bar val',
baz: 'baz val'
}
console.log(o)
// {Symbol(foo): foo val, ..., }
引用类型通常叫做类(Class),也就是说,遇到引用值,所处理的就是对象。
在 ECMA-262 标准中根本没有出现 类 这个词,而是定义了 对象定义,逻辑上等价于其他程序设计语言中的类。
对象是由 new 运算符加上要实例化的对象的名字创建的。
例如,下面的代码创建 Object 对象的实例:
var o = new Object();
这种语法与 Java 语言的相似,不过当有不止一个参数时,ECMAScript 要求使用括号。
如果没有参数,如以下代码所示,括号可以省略:
var o = new Object();
尽管括号不是必需的,但是为了避免混乱,最好使用括号。
对象定义为一组属性的无序集合。严格来说,这意味着对象就是一组没有特定顺序的值。
属性和方法
属性分为两种:数据属性和访问器属性。
数据属性
数据属性包含一个保存数据值的位置。值会从这个位置读取,也会写入到这个位置。数据属性有4个特性描述它们的行为。
Object.defineProperty(obj, key, descriptor)
访问器属性
访问器属性不包含数据值。相反,它们包含一个获取(getter)函数和一个设置(setter)函数,不过这个两个函数不是必需的。
在读取访问器属性时,会调用获取函数,这个函数的责任就是返回一个有效值。在写入访问器属性时,会调用设置函数并传入新值,这个函数必须决定对数据做出什么修改。
合并对象
方法接收一个目标对象和一个或多个源对象作为参数,然后将每个源对象中可枚举和自有属性赋值到目标对象。以字符串和符号为键的属性会被复制。
Object.assign(targetObject, sourceObject, ...)
Object.assign() 实际上对每个源对象执行的是浅复制。如果多个源对象都有相同的属性,则使用最后一个复制的值。
对象标识及相等判定
Object.is(Obj1, Obj2)
增强的对象语法
使用与对象匹配的解构来实现对属性的赋值。
ECMAScript5 将 Array.isArray() 正式引入 JavaScript,该方法能准确检测一个变量是否为数组类型。
Array.isArray(variable);
filter() 过滤
filter() 函数接收一个函数作为其参数,返回值为“true”的元素会被添加至新的数组中,返回值为“false”的元素则不会添加至新的数组中,最后返回这个新数组。如果没有符合条件的值则返回空数组。
针对简单类型的数组
let filterFn = function(x){
return x % 2;
}
let arr = [1, 2, 3, 5, 6]
let result = arr.filter(filterFn)
针对复杂类型而定数组
let filterFn = function(obj){
return obj.age > 18 && obj.gender === "男";
}
let arrObj = [
{
gender: '男',
age: 17
},
{
gender: '女',
age: 19
}
]
let result = arrObj.filter(filterFn)
reduce() 累加
reduce() 函数最主要的作用是做累加处理,即接收一个函数作为累加器,将数组中的每一个元素从左到右依次执行累加器,返回最终处理结果。
arr.reduce(callback(accumulator, currentValue, currentIndex?, array?)[, initialValue]);
let countOccurrences = function(arr){
return arr.reduce(function(accumulator, currentValue){
accumulator[currentValue]? accumulator[currentValue]++ : accumulator[currenValue]=1;
return accumulator;
},{});
};
countOccurences([1, 2, 3, 4, 5, 1])
let items = [{price: 10}, {price: 50}, {price: 100}]; let reducers = { totalInEuros: function(state, item){ return state.euros += item.price*0.1265; }, totalInDollars: function(state, item){ return state.euros += item.price*0.1478; }, }; let manageReducers = function(reducers){ return function(state, item){ function(nextState, key){ reducers[key](state, item); return state; } } } let bigTotalPriceReducer = manageReducers(reucers); let initialState = {euros: 0, dollars: 0}; let totals = items.reduce(bigTotalPriceReducer, initialState);
let now = new Data()
Map 是一种新的集合类型,实现“键/值”式存储机制,键可以为任意数据类型。
与 Object 类型的一个主要差异是,Map 实例会维护键值对的插入顺序,因此可以根据插入顺序执行迭代操作。
const m = new Map(); // 使用嵌套数组初始化映射 const m1 = new Map([ ["key1", "val1"]; ["key2", "val2"]; ["key3", "val3"]; ]); // 使用自定义迭代器初始化映射 const m2 = new Map({ [Symbol.iterator]: function*(){ yield ["key1", "val1"]; yield ["key2", "val2"]; yield ["key3", "val3"]; } }) // 实例方法 set("key", "val"); // 返回映射实例 get("key"); has("key"); delete("key"); clear("key");
弱映射中的键只能是 Object 或者继承自 Object 的类型,尝试使用非对象设置键会抛出 TypeError。值的类型没有限制。
const key1 = {id:1},
key2 = {id:2},
key3 = {id:3},
const wm1 = new WeakMap([
["key1", "val1"];
["key2", "val2"];
["key3", "val3"];
]);
Set 会维护值插入时的顺序,因此支持按准许迭代。集合
// 使用数组初始化集合 const s1 = new Set(["val1", "val2", "val3"]) // 使用自定义迭代器初始化集合 const s2 = new Set({ [Symbol.iterator]: function*(){ yield "val1"; yield "val2"; yield "val3"; } }) // 实例方法 add() has() delete() clear()
Arrary、Map、Set 定义了默认迭代器,因此都兼容扩展操作符。扩展操作符在对可迭代对象执行浅复制时特别有用。
let arr1 = [1, 2, 3];
let arr2 = [...arr1]
console.log(arr1 === arr2); // false
类型检测的方法:
typeof 操作符返回一个字符串,表示未经计算的操作数的类型。
// 原始数据类型 typeof 'foo'; // "string" typeof 100; // "number" typeof NaN; // "number" typeof true; // "boolean" typeof undefined; // "undefined" typeof myCar; // "undefined" (如果 myCar 没有声明) typeof null; // "object" typeof Symbol(); // "symbol" // 引用数据类型 typeof {}; // "object" typeof new Object(); // "object" typeof {name:'John', age:34}; // "object" typeof []; // "object" typeof [1, 2]; // "object" typeof function () {}; // "function" typeof new Date(); // "object" typeof new RegExp(); // "object"
typeof 操作符适合对 基本类型(除 null 之外)及 function 的检测使用,而对引用数据类型(如 Array)等不适合使用。
① instanceof 运算符用于检测一个对象在其 原型链 中是否存在一个构造函数的 prototype 属性,返回一个布尔值。
左操作数为对象,不是就返回 false,右操作数必须是 函数对象 或者 函数构造器,不是就返回 TypeError 异常。
obj instanceof constructor;
instanceof 左边值的__proto__ 是否能找到 instanceof 右边值的 prototype,如果能找到就返回 true 。
function Animal() {}
var ani = new Animal();
console.log(ani instanceof Animal); // true
console.log(ani.__proto__ === Animal.prototype); // true
console.log(ani.constructor); // ƒ Animal() {}
console.log(Animal.constructor); // ƒ Function() { [native code] }
console.log(ani);
console.log(Animal.prototype);
② instanceof 操作符可以正确的判断对象的类型:instanceof 操作符只能正确判断引用数据类型,而不能判断基本数据类型。
console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('str' instanceof String); // false
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object); // true
➂ instanceof 运算符用于测试构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
function Person() {} function Student() {} Student.prototype = new Person(); Student.prototype.constructor = Student; const ben = new Student(); ben instanceof Student; // true const one = new Person(); one instanceof Person; // true one instanceof Student; // false ben instanceof Person; // true
任何一个构造函数都有一个 prototype 对象属性,这个对象属性将用作 new 实例化对象的原型对象。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。