JSON.parse('{"p": 5}', function (k, v) {
if(k === '') return v; // 如果到了最顶层,则直接返回属性值,
return v * 2; // 否则将属性值变为原来的 2 倍。
}); // { p: 10 }
function censor(key, value) {
if (typeof(value) == "string") {
return undefined;
}
return value;
}
var foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7};
var jsonString = JSON.stringify(foo, censor);
JSON.stringify({ uno: 1, dos : 2 }, null, '\t')
var obj = {
foo: 'foo',
toJSON: function () {
return 'bar';
}
};
JSON.stringify(obj); // '"bar"'
JSON.stringify({x: obj}); // '{"x":"bar"}'
shorthand properties(属性的简写)
ES6允许在对象之中,只写属性名,不写属性值。这时,属性值等于属性名所代表的变量
var firstName = 'Edward';
var lastName = 'Ann';
var personA = {firstName: firstName, lastName: lastName};
var personB = {firstName, lastName};
personA //Object {firstName: "Edward", lastName: "Ann"}
personB //Object {firstName: "Edward", lastName: "Ann"}
除了属性简写,方法也可以简写(注意,简洁写法的属性名总是字符串)
var personC = {
name: 'edward',
sayHello() {
console.log(this.name + ' hello');}}
personC.sayHello(); //edward hello
ES6允许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在方括号内
var person1 = {
firstName: 'Teddy',
lastName: 'John'
};
let propKey1 = 'firstName';
let propKey2 = 'lastName';
let person2 = {
[propKey1]: 'Ann',
[propKey2 + 'test']: 'Lynn'
}
person1 //Object {firstName: "Teddy", lastName: "John"}
person2 //Object {firstName: "Ann", lastNametest: "Lynn"}
表达式还可以用于定义方法名
let salut = {
['say' + 'hi']() {
console.log("hi");
}
}
salut.sayhi() // hi
字符串也可以作为对象中方法名的key
let animal1 = {
"say hi"() {console.log('hi')}
}
animal1["say hi"]() //hi
用表达式作为属性访问器(getter,setter)的定义(实际使用中很少使用)
function getCar(make, model, value) {
let x = "value";
return {
make,
model,
_value: value,
get [x]() {
return this._value;
},
set [x](value) {
if (value < 0)
throw new Error('invalid value');
this._value = value;
}
};
}
let car = getCar('Kia', 'Sorento', 40000);
console.log(car.value);//40000
car.value = 30000;//3000
car.value = -100;//Uncaught Error: invalid value(…)
注意,属性名表达式与简洁表示法,不能同时使用,否则会报错
let Rayn = 'Bill';
let newPerson = {
[Rayn]: 'Bill'
}
let newPerson1 = {
Rayn
}
//下面的写法会报错
let newPerson2 = {
[Rayn]
}
hoisted lock-level function declaration
在ECMAScript3和更早之前,在块级作用域内声明函数会直接报错,但是很多的浏览器依然支持这个特性,当然在实现上稍有不一。为了解决这种兼容性问题,ECMAScript5的严格模式下定义,当在块级作用里面定义了一个函数时,就会报错。
"use strict";
if (true) {
// Throws a syntax error in ES5, not so in ES6
function doSomething() {
// ...
}
}
在ECMAScript 6中,上面的doSomething()函数被认为是被认为是块级层面的声明并且能够在同一个块级作用域内被访问到。即事实上它的声明被提升到了同样块级的顶部。
"use strict";
if (true) {
console.log(typeof doSomething); // "function"
function doSomething() {
// ...
}
doSomething();
}
console.log(typeof doSomething); // "undefined"
A function is declared and only referenced within a single block
A function is declared and possibly used within a single Block but also referenced by an inner function definition that is not contained within that same Block.
A function is declared and possibly used within a single block but also referenced within subsequent blocks
Labelled Function Declarations
标记语句(labeled statement)可以和 break 或 continue 语句一起使用。标记就是在一条语句前面加个可以引用的标识符(identifier)
var i, j;
loop1:
for (i = 0; i < 3; i++) { //The first for statement is labeled "loop1"
loop2:
for (j = 0; j < 3; j++) { //The second for statement is labeled "loop2"
if (i == 1 && j == 1) {
continue loop1;
}
console.log("i = " + i + ", j = " + j);
}
}
但是在ECMAScript 2015之前,标记语句是不允许用于函数定义的,但是,被标记的函数定义在非严格模式下是允许扩展的,同时很多浏览器也提供了不一的实现。所以在ES6中,对这部分提供了支持。(注意如果是严格模式下依然会报语法错误)
LabelledItem : FunctionDeclaration
function statements in if-statement clauses
分成了四种类型
if ( Expression) FunctionDeclaration else Statement
if ( Expression) Statement else FunctionDeclaration
if ( Expression ) FunctionDeclaration else FunctionDeclaration
if ( Expression) FunctionDeclaration
if(true) function y(){return 1} else function yy(){return 2}
yy() //VM3511:1 Uncaught TypeError: yy is not a function(…)
y() //1
只能在非严格模式下使用
之前这个一直只是浏览器端独有的扩展,在其它ECMAScript的实现中是不支持的。
<!-- Another comment
var tt = 3; <!-- Another comment
var ty = 4;
此方法能够拦截Object.getOwnPropertyDescriptor()操作,返回值是对象或者undefined
var p = new Proxy(target, {
getOwnPropertyDescriptor: function (target, prop) {
//code
}
})
7). 如果属性不是对象的自有属性,或者此属性是对象可配置自有属性,那么返回属性描述对象configurable属性值必须为true,否则报错。
let antzone = {
webName: "testBefore",
url:"test"
};
var p = new Proxy(antzone, {
getOwnPropertyDescriptor: function(target, prop) {
return { configurable: true, enumerable: true, value: "testAfter" };
}
});
Object.getOwnPropertyDescriptor(antzone, "webName");
Object.getOwnPropertyDescriptor(p, "webName");
//此时如果返回是undefined则会报错
Object.defineProperty(antzone, "webName", {
writable: true,
enumerable: true,
configurable: false
})
此方法可以拦截Object.getOwnPropertyNames(),Object.getOwnPropertySymbols(),Object.keys(),Reflect.ownKeys操作,返回值是一个数组
var p = new Proxy(target, {
ownKeys: function (target) {
//code
}
});
5). 如果target对象是不可扩展的,那么返回数组必须且只包含target对象所有的自有属性名称。
var antzone = {
webName: "test",
url: "test1",
}
var p = new Proxy(antzone, {
ownKeys: function(target) {
return ["a", "b", "c"];
}
});
Object.getOwnPropertyNames(p);
//下面的会报错,因为返回数组必须包含所有target对象自有不可配置的属性名称
var antzone = {
webName: "test",
url: "test1",
}
Object.defineProperty(antzone, "webName", {
configurable: false
})
var p = new Proxy(antzone, {
ownKeys: function(target) {
return ["url"];
}
});
Object.getOwnPropertyNames(p);
//下面会报错,因为antzone是不可扩展的,所以返回数组必须且只包含target对象所有的自有属性名称
var antzone = {
webName: "test",
url: "test1",
}
Object.preventExtensions(antzone);
var p = new Proxy(antzone, {
ownKeys: function(target) {
return ["url"];
}
});
Object.getOwnPropertyNames(p);