基本类型的包装对象
“包装对象”对于每种基本类型调用都是不同的,如String, Number, Boolean 和 Symbol。因此,他们提供了不同的方法。基本类型 null 和 undefined 是个例外。他们没有相应的“包装对象”,也没有提供任何方法。
数字类型–JavaScript中所有的数字都以64位格式IEEE-754存储
<script>
let num = 255;
/* 1. 将数字转化为几进制 toString(base) */
console.log(num.toString(16));
console.log(num.toString(2));
console.log(12345..toString(36));
// 注意:数字调用时请注意 123456..toString(36) 中的两个点不是拼写错误。如果我们想直接在一个数字上调用一个方法,比如上面例子中的 toString,那么我们需要在它后面放置两个点 ..。如果我们放置一个点:123456.toString(36),那么会出现错误,因为 JavaScript 语法暗示了第一个点之后的小数部分。如果我们再放一个点,那么 JavaScript 知道小数部分是空的,现在进入方法。
/* 2. 向下舍入 */
console.log(Math.floor(3.1));
console.log(Math.floor(3.6));
console.log(Math.floor(-1.1))
console.log(Math.floor(-1.6));
/* 3. 向上舍入 */
console.log(Math.ceil(3.1));
console.log(Math.ceil(3.6));
console.log(Math.ceil(-1.1))
console.log(Math.ceil(-1.6));
/* 4. 四舍五入 */
console.log(Math.round(3.1));
console.log(Math.round(3.6));
console.log(Math.round(-1.1))
console.log(Math.round(-1.6));
/* 5. 取整(IE不支持trunc这个方法) */
console.log(Math.trunc(3.1));
console.log(Math.trunc(3.6));
console.log(Math.trunc(-1.1))
console.log(Math.trunc(-1.6));
/* 6.测试isFinite和isNaN */
// isNaN(value) 将其参数转换为数字,然后测试它是否为 NaN:
console.log(isNaN(NaN));
console.log(NaN === NaN); //false
// isFinite(value) 将其参数转换为数字,如果是常规数字,则返回 true,(NaN / Infinity / -Infinity是非常规数字),否则返回false
alert( isFinite("15") ); // true
alert( isFinite("str") ); // false
alert( isFinite(Infinity) ); // false
</script>
可迭代对象
可迭代对象是数组的泛化,这个概念是说任何对象都可在 for…of 循环中使用。]
可迭代对象:有Symbol.iterator方法的对象
类数组对象:有索引和length属性的对象
obj[Symbol.iterator] 的结果被称为迭代器。由它处理更深入的迭代过程。
一个迭代器必须有 next() 方法,它返回一个 {done: Boolean, value: any},这里 done:true 表明迭代结束,否则 value 就是下一个值。
<script>
/* 1. 创建一个可迭代对象
1. 为对象添加一个Symbol.iterator的方法
2. 当for..of循环开始,它就会调用这个方法,如果没有找到,就报错
3. 这个方法必须返回一个迭代器 —— 一个有 next 方法的对象。
4. 当 for..of 循环希望取得下一个数值,它就调用这个对象的 next() 方法。
5. next() 返回结果的格式必须是 {done: Boolean, value: any},当 done=true 时,表示迭代结束,否则 value 必须是一个未被迭代的新值。
*/
let range = {
from: 1,
to: 5
};
range[Symbol.iterator] = function () {
return {
current: this.from,
last: this.to,
next() {
if (this.current <= this.last) {
return {
done: false,
value: this.current++
};
} else {
return {
done: true
};
}
}
}
}
for (let num of range) {
alert(num);
}
// 技术上说,我们可以将它们合并,用 range 自身作为迭代器来简化代码。
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
this.current = this.from;
return this;
},
next() {
if (this.current <= this.to) {
return {
done: false,
value: this.current++
};
} else {
return {
done: true
};
}
}
};
for (let num of range) {
alert(num); // 1, 然后 2, 3, 4, 5
}
// 显示调用迭代器
let string = 'Hello';
let iterator = string[Symbol.iterator]();
while (true) {
let result = iterator.next();
if (result.done)
break;
alert(result.value);
}
</script>
Map
Map 是一个键值对的集合,很像 Object。但主要的区别是,Map 允许所有数据类型作为键。
- new Map(): 创建 map。
- map.set(key, value): 根据键(key)存储值(value)。
- map.get(key): 根据键返回值,如果 map 中该键不存在,返回 undefined。
- map.has(key): 如果键存在,返回 true,否则返回 false。
- map.delete(key): 移除该键的值。- map.clear(): 清空 map
- map.size:返回当前元素个数。
Set
Set 是一个值的集合,这个集合中所有的值仅出现一次。
- new Set(iterable):创建 set,利用数组来创建是可选的(任何可迭代对象都可以)。
- set.add(value):添加值,返回 set 自身。
- set.delete(value):删除值,如果该 value 在调用方法的时候存在则返回 true ,否则返回 false。
- set.has(value):如果 set 中存在该值则返回 true ,否则返回 false。
- set.clear():清空 set。
- set.size:元素个数。
WeakSet和WeakMap
WeakSet 是一种特殊的 Set,它不会阻止 JavaScript 将它的元素从内存中移除。WeakMap 和 Map 的区别也和上述一样。
WeakMap
- 它和 Map 的第一个区别是它的键必须是对象,不能是基础类型的值
如果我们使用对象作为它的键,并且没有任何引用指向这个对象, 它将会自动被从内存中移除(也会从 map 中移除)。 - WeakMap 并不支持方法 keys(),values(),entries(),我们不能对它进行迭代。所以没有办法获取它的所有键值。方法:
weakMap.get(key)
weakMap.set(key, value)
weakMap.delete(key, value)
weakMap.has(key)
WeakSet
只能将对象添加进 WeakSet(不可以是基础类型)
仅当对象存在其他位置的引用时它才存在于 set 中。
就像 Set 一样,它支持 add,has 和 delete,不支持 size,keys()也不支持迭代器。
WeakMap/WeakSet 的主要任务 —— 作为对象的附加存储,该对象在其他位置被保存或管理。
对象的键,值,项
Object.keys(obj) // 返回一个包含该对象全部的键的数组
Object.values(obj) // 返回一个包含该对象全部的值的数组
Object.entries(obj) // 返回一个包含该对象全部[key,value]键值对的数组
Object.getOwnPropertySymbols() // 返回一个只包含Symbol类型的键的数组
Reflect.ownKey(obj); // 返回所有键
<script>
let user = {
name:'叶叶',
age : 30
};
console.log(Object.keys(user));
console.log(Object.values(user));
console.log(Object.entries(user));
console.log(Object.getOwnPropertySymbols(user));
console.log(Reflect.ownKeys(user));
</script>
JSON
JSON (JavaScript Object Notation) 是表示值和对象的通用格式。它被描述为 RFC 4627 标准。最初它是为 JavaScript 编写的,但许多其他语言也有库来处理它。
JSON 是跨语言的纯数据规范,因此一些特定于 JavaScript 的对象属性被 JSON.stringify 跳过 如:
- 函数属性(方法)。
- Symbolic 属性。
- 存储 undefined 的属性
方法:
- JSON.stringify 将对象转换为 JSON。
得到的 json 字符串是一个被称为 JSON 编码或者序列化或者字符串化或者编组的对象。我们准备好通过网线传输或存储。如果一个对象具有 toJSON()方法,那么它可被 JSON.stringify 调用。 - JSON.parse 将 JSON 转换回对象。
<script>
/* 1. stringify
JSON.stringify(value[,replacer,space]);
value 要编码的值
replacer 要编码的属性数组,或映射函数function(key,value)
space 文本添加缩进,空格和换行符
*/
let student = {
name: 'John',
age: 30,
isAdmin: false,
courses: ['html', 'css', 'js'],
wife: null
};
// 1.1 只使用第一个参数
let json = JSON.stringify(student);
alert(typeof json); //string
alert(json);
//{"name":"John","age":30,"isAdmin":false,"courses":["html","css","js"],"wife":null}
let room = {
number: 23
};
let meetup = {
title: "Conference",
participants: [{
name: "John"
}, {
name: "Alice"
}],
place: room // meetup references room
};
room.occupiedBy = meetup; // room references meetup
// 1.2 第二个参数使用数组, 如果我们需要微调替换过程,比如过滤掉循环引用,我们可以使用 JSON.stringify 的第二个参数。如果我们传递一组属性给它,只有这一组属性会被编码
json = JSON.stringify(meetup, ['title', 'participants']);
alert(json); //{"title":"Conference","participants":[{},{}]}
// 1.3 第二个参数使用映射函数: 让我们包含除了会导致循环引用的 room.occupiedBy 之外的所有属性
json = JSON.stringify(meetup, function replacer(key, value) {
alert(`${key}:${value}`);
return (key == 'occupiedBy') ? undefined : value;
});
alert(json);
// 1.4 第三个参数:格式化 所有字符串化的对象都没有缩进和额外的空格。现在,如果我们想通过网络发送一个对象。spacer 参数可以更好的输出。
/*
alert(JSON.stringify(student, null, 2)); {
"name": "John",
"age": 25,
"roles": {
"isAdmin": false,
"isEditor": true
}
}
*/
</script>
解构赋值
解构赋值是一种特殊的语法,它让我们可以将数组或对象进行“拆包”,存放到一系列的变量中,因为有时候使用变量更加方便。解构操作在那些具有很多参数和默认参数值的函数中也很奏效. 通过将结构中的各元素复制到变量中来达到“解构”的目的。但是其本身是没有被修改的。
**数组解构(实际可用于任何可迭代对象) **
let arr = ['li','叶叶'];
let [firstName,lastName] = arr;
console.log(firstName);
console.log(lastName);
// 和返回数组的函数组合使用
let [frstName, surname] = "Ilya Kantor".split(' ');
console.log(frstName);
console.log(surname);
// 忽略元素
let[,, title] = ["Julius","Caesar","Consul","of the Roman Republic"];
console.log(title);
// 用于可迭代对象
let [a,b,c] = "abc";
console.log(a);
console.log(b);
console.log(c);
// 等号左侧可以是任何可以被赋值的变量
let user ={};
[user.name,user.age] = ['李叶叶',18];
console.log(user);
// 使用Object.entries(obj)方法和解构语法来遍历一个对象的键值对
for(let [key,value] of Object.entries(user)){
console.log(`${key}:${value}`);
}
// 如果我们不仅要获得第一个值,还要将后续的所有元素也收集起来——我们可以使用三个点 "..." 加一个参数来接收“剩余的”元素:
let [name1,name2,...rest] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
console.log(name1);
console.log(name2);
console.log(rest[0]);
console.log(rest[1]);
console.log(rest.length);
// 如果赋值语句中变量的数量多于数组中实际元素的数量,赋值不会报错。未赋值的变量被当作 undifined
let [num1,num2] = [];
console.log(num1);
console.log(num2);
// 如果我们想要提供一个“默认值”给未赋值的变量,我们可以使用 = 来提供:
let [str1='li',str2='叶叶']=["李"];
console.log(`${str1}:${str2}`);
对象解构
let {var1, var2} = {var1:…, var2…}
在等号右侧有一个已经存在的对象,我们想把它拆开到变量中。等号左侧包含了对象相应属性的一个“模式”。
let options ={
title: 'Menu',
width:100,
height: 200
};
let {title,width,height} = options;
console.log(title);
console.log(width);
console.log(height);
// 给属性和变量之间指定一个映射关系。
// { 原属性:目标变量 }
let {width: w,height:h,title} = options;
console.log(w);
console.log(h);
console.log(title);
let a,b,c;
{a,b,c} = {a:10,b : 5, c:10}; // 报错,问题在于 JavaScript 把主代码流(即不在其他表达式中)的 {...} 当做一个代码块,这样的代码块可以被用来组织语句.为了告诉 JavaScript 这不是一个代码块,我们可以把整个赋值表达式用括号 (...) 包起来:
({a,b,c} = {a:10,b : 5, c:10});
console.log(a);
console.log(b);
console.log(c);
嵌套解构
let options = {
size: {
width:100,
height:200
},
items : ['Cake','Donut'],
extra : true
};
let{
size:{
width,
height
},
items:[item1,item2],
title='Menu' // 在对象中不存在的属性(会使用默认值)
}=options;
console.log(title); // Menu
console.log(width); // 100
console.log(height); // 200
console.log(item1); // Cake
console.log(item2); // Donut