一、js 判断对象是否为空
1、将 json 对象转化为 json 字符串,再判断该字符串是否为 "{}"
var data = {};
var b = (JSON.stringify(data) == "{}");
alert(b); // true
复制代码
注意: 忽略转换 undefined、function、Symbol 属性
JSON.stringify({[Symbol("key")]: "foo"}); // {}
复制代码
2、for in 循环判断
var obj = {};
var b = function() {
for(var key in obj) {
return false;
}
return true;
}
alert(b()); // true
复制代码
3、jquery 的 isEmptyObject()
此方法是 jquery 将 2 方法 (for in) 进行封装,使用时需要依赖 jquery
var data = {};
var b = $.isEmptyObject(data);
alert(b); // true
复制代码
4、Object.getOwnPropertyNames()
获取到对象中的属性名,存到一个数组中,返回数组对象,我们可以通过判断数组的 length 来判断此对象是否为空
var data = {};
var arr = Object.getOwnPropertyNames(data);
alert(arr.length === 0); // true
复制代码
注意:此方法不兼容 IE8
5、使用 ES6 的 Object.keys()
与 4 方法类似,是 ES6 的新方法, 返回值也是对象中属性名组成的数组
var data = {};
var arr = Object.keys(data);
alert(arr.length === 0); // true
复制代码
二、js 遍历对象
1、for in
循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
var obj = {'0': 'a', '1': 'b', '2': 'c'};
for (var i in obj) {
console.log(i, obj[i]);
}
复制代码
2、Object.getOwnPropertyNames()
返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性).
var obj = {'0': 'a', '1': 'b', '2': 'c'};
Object.getOwnPropertyNames(obj).forEach((key) => {
console.log(key, obj[key]);
});
复制代码
3、Object.keys()
返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)
var obj = {'0': 'a', '1': 'b', '2': 'c'};
Object.keys(obj).forEach((key) => {
console.log(key, obj[key]);
});
复制代码
4、Reflect.ownKeys()
返回一个数组,包含对象自身的所有属性,不管属性名是 Symbol 或字符串,也不管是否可枚举
var obj = {'0': 'a', '1': 'b', '2': 'c'};
Reflect.ownKeys(obj).forEach(function(key) {
console.log(key, obj[key]);
});
复制代码
三、js 数组遍历
1、for
var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i ++) {
console.log(i, arr[i]);
}
复制代码
2、forEach
var arr = [1, 2, 3];
arr.forEach(function(val, index) {
console.log(val, index);
});
复制代码
3、for in
var arr = [1, 2, 3];
for (var i in arr) {
console.log(i, arr[i]);
}
复制代码
4、for of
不仅支持数组,还支持大多数类数组对象
也支持字符串遍历,它将字符串视为一系列的 Unicode 字符来进行遍历
var arr = [1, 2, 3];
for (var value of arr) {
console.log(value);
}
复制代码
5、数组/对象数组中获取 id
let arr = [{
id: 0,
text: 'a'
}, {
id: 1,
text: 'b'
}];
let str = arr.map( (item) => {
return [item.id]; // 字符串、数组、对象
});
复制代码
四、数据类型
1、原始数据类型
null 空值
undefined 变量未初始化
Number 数字类型
String 字符串
boolean 布尔型
Object 对象
复制代码
2、ES6 Symbol
-
概述
Symbol 数据类型是一个原始数据类型
Symbol 是一种特殊的、不可变的数据类型,可以作为对象属性的标识符使用
Symbol 对象是一个 symbol primitive data type 的隐式对象包装器
-
语法格式
Symbol([description]) // description 是可选的 字符串
Symbol 的描述,可用于调试(便于区分 Symbol 值)但不能访问 Symbol 本身
-
Number
const b = Number(10); // 10 const b = 10; // 简写
-
Symbol
const name = Symbol(); const name1 = Symbol('sym1'); console.log(name, name1) // Symbol() Symbol(sym1)
-
-
Symbol 转码 需要 babel 及 babel-polyfill
babel默认只转换新的JavaScript句法(syntax),而不转换新的API,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。如果想让这个方法运行,必须使用 babel-polyfill,为当前环境提供一个垫片。
-
Symbol 特点
- 1、Symbol 不能使用 new
const name = new Symbol();
- 2、每个从 Symbol() 返回的 symbol 值都是唯一的
一个 symbol 值能作为对象属性的标识符
Symbol("foo") 不会强制字符串 “foo” 成为一个 symbol类型
它每次都会创建一个新的 symbol类型:
Symbol("foo") === Symbol("foo"); // false Symbol.for('foo') === Symbol.for('foo'); // true 复制代码
Symbol.for() 与 Symbol() 这两种写法,都会生成新的 Symbol
它们的区别是,前者会被登记在全局环境中供搜索,后者不会
Symbol.for() 不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的 key 是否已经存在,如果不存在才会新建一个值,比如,如果你调用 Symbol.for("cat") 30 次,每次都会返回同一个 Symbol 值,但是调用 Symbol("cat")30 次,会返回 30 个不同的 Symbol 值
- 3、可以使用
Object.defineProperty()
和Object.defineProperties()
方法
在一个对象上定义新的属性
// 设置对象属性只读。 Object.defineProperty(obj, name, {writable: false}); Object.defineProperty(props, 'key', { get: warnAboutAccessingKey, configurable: true }); 复制代码
- 4、全局共享
Symbol 在 js 文件中定义的 Symbol,并不能在其他文件直接共享
要创建跨文件可用的 symbol,甚至跨域(每个都有它自己的全局作用域), 使用 Symbol.for() 方法和 Symbol.keyFor() 方法从全局的 symbol 注册表中设置和取得。
Symbol.for() // 只有一个参数
Symbol.keyFor() // 只有一个参数,返回的是key
let name = Symbol.for('000'); let name1 = Symbol.for('111'); let name2 = Symbol.for('222'); console.log(Symbol.keyFor(name)); // 000 console.log(Symbol.keyFor(name1)); // 111 console.log(Symbol.keyFor(name2)); // 222 复制代码
- 5、Symbol 不支持类型强制转换
let a = 1; console.log(typeof a); // number console.log(a + ' haha') // '1haha' Symbol 不支持强制转换 let a = Symbol('a'); console.log(typeof a); console.log(a + ' haha'); // Cannot convert a Symbol value to a string 复制代码
- 6、Symbol 检索
Symbol 作为属性名,该属性不会出现在
for...in
、for...of
循环中也不会被
Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回但是,它也不是私有属性,有一个 ES6 新增的方法
Object.getOwnPropertySymbols
方法可以获取指定对象的所有 Symbol 属性名
let a = Symbol('a'); let b = Symbol('b'); let obj = { [a]: '123', [b]: 45 } for (let value of Object.getOwnPropertySymbols(obj)) { console.log(obj[value]); // "123" 45 } 复制代码
- 7、Object.getOwnPropertySymbols
使用 Object.getOwnPropertyNames 方法得不到Symbol属性名,需要使用
Object.getOwnPropertySymbols
方法const obj = {}; let foo = Symbol("foo"); Object.defineProperty(obj, foo, { value: "foobar", }); for (let i in obj) { console.log(i); // 无输出 } Object.getOwnPropertyNames(obj); // [] Object.getOwnPropertySymbols(obj); // [Symbol(foo)] 复制代码
- 8、Reflect.ownKeys
还有一个上面提到的 Reflect.ownKeys 方法可以返回所有类型的键名,包括常规键名和 Symbol 键名
let obj = { [Symbol('my_key')]: 1, enum: 2, nonEnum: 3 }; Reflect.ownKeys(obj); // ["enum", "nonEnum", Symbol(my_key)] 复制代码
- 9、typeof 运算符
typeof Symbol('foo') === 'symbol' 复制代码
- 10、在所有使用可计算属性名的地方,都能使用 Symbol 类型。比如在对象中的key
const name = Symbol('name'); const obj = { [name]: "haha" } console.log(obj[name]); // haha 复制代码
- 11、Symbol 包装器对象作为属性的键
var sym = Symbol('foo'); var obj = {[sym]: 1}; obj[sym]; // 1 obj[Object(sym)]; // still 1 复制代码
-
实例: 消除魔术字符串
- 消除魔术字符串,消除强耦合
function getArea(shape, options) { let area = 0; switch (shape) { case 'Triangle': // 魔术字符串 area = .5 * options.width * options.height; break; /* ... more code ... */ } return area; } getArea('Triangle', { width: 100, height: 100 }); // 魔术字符串 复制代码
- 定义一个变量
const shapeType = { triangle: 'Triangle' }; function getArea(shape, options) { let area = 0; switch (shape) { case shapeType.triangle: area = .5 * options.width * options.height; break; } return area; } getArea(shapeType.triangle, { width: 100, height: 100 }); 复制代码
- Symbol 值
如果仔细分析,可以发现 shapeType.triangle 等于哪个值并不重要
只要确保不会跟其他 shapeType 属性的值冲突即可
因此,这里就很适合改用 Symbol 值
const shapeType = { triangle: Symbol() }; 复制代码