携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情 >>
昨夜西风凋碧树。独上高楼,望尽天涯路。
基本类型
- 空值(null)
- 未定义(undefined)
- 布尔值(boolean)
- 数字(number)
- 字符串(string)
- 符号(symbol,ES6中新增)
空值(null)和未定义(undefined)
typeof null // object
typeof undefined // undefined
typeof
根据二进制判断,所以 typeof null 被判断成了对象
-
000:对象
-
1:整数
-
010:浮点数
-
100:字符串
-
110:布尔
有 2 个值比较特殊:
-
undefined:用 - (−2^30)表示。
-
null:对应机器码的 NULL 指针,一般是全零。
if (JSVAL_IS_VOID(v)) { // (1) type = JSTYPE_VOID; } else if (JSVAL_IS_OBJECT(v)) { // (2) obj = JSVAL_TO_OBJECT(v); if (obj && (ops = obj->map->ops, ops == &js_ObjectOps ? (clasp = OBJ_GET_CLASS(cx, obj), clasp->call || clasp == &js_FunctionClass) // (3,4) : ops->call != 0)) { // (3) type = JSTYPE_FUNCTION; } else { type = JSTYPE_OBJECT; } } else if (JSVAL_IS_NUMBER(v)) { type = JSTYPE_NUMBER; } else if (JSVAL_IS_STRING(v)) { type = JSTYPE_STRING; } else if (JSVAL_IS_BOOLEAN(v)) { type = JSTYPE_BOOLEAN; }
注释(1):判断是否为 undefined
注释(2):如果不是 undefined,判断是否为对象
注释(3):判断值是否有对象的标志位。如果它是可调用的,或者说通过内部属性[[Class]]可以表明它是一个函数。否者它就是一个对象
这样一来,null 就出了一个 bug。根据 type tags 信息,低位是 000,因此 null 被判断成了一个对象。这就是为什么 typeof null 的返回值是 object。
instanceOf
instanceof 是通过原型判断是否是同一类型
function _instanceof(l, r) {
var o = r.prototype;
l = l.__proto__;
while (true) {
if (l === null) {
return false;
}
if (o === l) {
return true;
}
l = l.__proto__;
}
}
number
JavaScript 能够准确表示的整数范围在-2^53
到2^53
之间(不含两个端点),超过这个范围,无法精确表示这个整数
基本类型的封装类型
字符串布尔类型都有方法,是因为使用对应的变量时,编译器会将其装箱成对应的对象类型,例如 var s = 'test',如果使用s变量时会将s = new String(s)进行封装,一旦属性引用结束,这个新创建的对象就会被销毁。
var s = 'test';
s == new String(s) // true
s.len = 4
s.len // undefined
隐士类型转换
-
字符串和数字之间相等的比较
字符串和数字之间相等的比较
'42' == 42 // true Number('42') == 42
-
其他类型和Boolean类型值比较
Boolean 类型转换成number
'42' == true // false '42' == Number(true)1
-
Null 与 undefined
Null == undefined // true
-
NaN
NaN == NaN false NaN !=NaN true
-
对象与非对象的比较
通过ToPrimative(Obj) 获取对象的字符串值或者数值
42 == [42] // true
- ToNumber
> 为了将值转换为基本数据类型,抽象操作ToPrimitive会先检查该值是否有valueof()方法,没有然后在检查是否有通toString()方法
```javascript var a = { valueOf:function(){ return '23' }, toString:function(){ return '12' } } Number(a) // 23 a == 23 // true var a = { toString:function(){ return '12' } } Number(a) // 12 ```
-
JSON.stringify(会发生强制toString()类型转换
- 字符串、数字、布尔值和null的转换规则和ToString一致
- 如果传递给JSON.stringify的对象中定义了toJSON方法,那么该方法会在字符串化前调用,以便将对象转化成安全的JSON值
var a ={ name:'wky', age:10, toJSON:function(){ return this.name } } JSON.stringify(a) ;// ""wky""
symbol
1. Symbol 是基本数据类型
Symbol 是基础数据类型之一 typeof Symbol() 返回symbol
2. Symbol 不支持构造函数方式
new Symbol() 会报错
3. Symbol 使用方法
Symbol 会生成一个唯一的标识(不会重复)
var symbol1 = Symbol('aa');
var symbol2 = Symbol('bb');
symbol1 == symbol2 // 输出 false
4. Symbol 函数 for 和 keyFor
for函数生成唯一的Symbol数据, keyFor返回Symbol数据类型的key值
Symbol.for('eeee'); // Symbol(eeee)
Symbol.keyFor(Symbol.for('eee')) // 返回eee
5. 具体使用场景
var obj11 ={
name:'zhangsan'
}
var obj21 = {
name:'李四'
}
var obj31 = Object.assign(obj11, obj21);
console.log(obj31);
// 其中一个名字被融合没了
// 具体使用场景
var obj1 ={
[Symbol('name')]:'zhangsan'
}
var obj2 = {
[Symbol('name')]:'李四'
}
var obj3 = Object.assign(obj1, obj2);
console.log(obj3,'obj3');
// 不会被融合
6.模拟实现Symbol类型
(function(){
var getOVFnName = (function(){
let index = 0;
return function(desc) {
index = index +1;
return index + '-' + desc;
}
})();
function SymbolPolify (desc){
var symbol = Object.create({
toString(){
return this.__name__
}
})
Object.defineProperty(symbol, '__name__', {
value: getOVFnName(desc)
});
return symbol;
}
var d = SymbolPolify('dddd');
var a = SymbolPolify('aaaaa');
console.log(d, 'd');
console.log(a, 'a');
})()
引用类型
- Array
- Object
- Function
- Date
- Regx
Array
- sort
方法默认是按''排序 如果数据里是数组,也会将数字转换成字符串进行排序
扩展知识 V8 sort 排序: 数据量少的时候是用插入排序算法,数据量大的时候是用的快排算法
2. 操作方法
- concat
var list1 = [1, 3, 4];
var concatList = list1.concat([4, 5, 6]).concat([[8, 9, 10]]);
// 返回数组
console.log(concatList); [1,3,4,4,5,6,[8,9,10]]
- slice 数组截取方法
- 返回截取后的数组 startIndex endIndex endIndex不包含
- 如果endIndex 为负数,则截取的是 倒数第几个数 当然也不包含endIndex的索引值
const sliceList = concatList.slice(0, 4);
console.log(sliceList); [1,3,4,4]
-
splice 方法 删除 插入 替换 返回删除的数组 ,如果没有删除,则返回一个空数组
-
删除 startIndex deleteItems (从哪里开始删除,删除多少项数据)
-
插入 startIndex, deleteItems, insertObj (从哪里开始插入,0,要插入的数据)
-
替换 startIndex, deleteItems, repleaceObjs(从哪里开始替换,替换几项,替换的项)
-
- 位置方法
- indexOf 从数组的开头开始查找
- lastIndexOf 从数组的结尾开始查找
接收两个参数: value, index : 要查找的value值和查找起点位置的索引 , value值是=== 才会返回
// indexOf
const index = concatList.indexOf('4'); concatList.indexOf(4);
console.log(index); // -1 2
const lastIndex = concatList.lastIndexOf(4)
console.log(lastIndex); // 4
-
迭代方法
- every
- filter
- forEach
- map
- some
params: function(value, index, array), this
-
归并方法
- reduce 从数组的开头开始归并
- reduceRight 从数组的结尾开始归并
params: function(result, nextValue, index, array), initValue(数组为空时必须付初始值,不然会报错) var reduceList = []; var sum = reduceList.reduce((val, nextVal) => { return val + nextVal; }, 0) // 必须给最初的初始值 console.log(sum); // 0
Object Es6中新增的方法
- set 不会给对象中新增属性
var setObj1 = {
names:[],
set name (x){
return this.names.push(x);
},
// get name (){
// return this.names
// }
}
console.log( setObj1.name ) // undefined set不会新增属性信息
- Object.freeze 冻结对象
被冻结的对象不能修改属性值,也不能删除属性,也不能修改属性的可读写性可枚举性等信息
var setObj1 = {
names:[],
age: 20,
set name (x){
return this.names.push(x);
},
get name (){
return this.names
}
}
setObj1.name = 'nihao';
console.log(setObj1.name, setObj1.names);
var freezeO = Object.freeze(setObj1);
freezeO.names= [];
console.log(freezeO === setObj1);
freezeO.age = 30;
console.log(freezeO); // {names:[nihao], age: 20} 不能修改信息值 不会改变
- Object.seal
密封一个对象 可以修改属性值 但是不能删除或者新增属性
Function
function 和 arguments
- 函数形参和实参 在函数体中存在一个形参的引用,指向当前传入的实参列表,通过它可以获得参数的值
- 函数体内this指向 在严格模式中this 指向 undefined
- arguments 是指向实参对象的引用
- arguments中的数组 与形参是别名的关系
- 严格模式下 arguments是个保留字,并且不能被重新赋值
- 非严格模式下 arguments是个标识符, 能被修改
var a = 5;
function test(a){
a = 10
console.log(a, 'inner'); // 10
}
test();
console.log(a, 'wrap') // 5
function testArguments(b){
arguments[0] = 20;
console.log(b, 'inner arguments') // 20
}
testArguments(a);
console.log(a, 'wrap arguments') // 5
var list = [];
function testArray(list){
list.push(10);
console.log(list,'inner'); // [10]
}
testArray(list);
console.log(list, 'wrap'); // [10]