ES6 標(biāo)準(zhǔn)入門第2版 筆記


看這本書是在markdown在做的筆記,更友好的閱讀方式訪問: github es6.md(https://github.com/EarlyBirdss/Study-Diary/blob/master/es6.md)

ES6

https://babeljs.io/repl/ 在線轉(zhuǎn)碼


let


let 聲明一個(gè)變量, 只在let命令所在的代碼塊有效(非常適合在for循環(huán)中)

let沒有變量提升, 這意味著typeof不再是百分比安全的操作

只要在塊級(jí)作用域中存在let命令,它所在聲明的變量就綁定(binding)在這個(gè)區(qū)域, 不受外界影響

暫時(shí)性死區(qū):在代碼塊內(nèi)使用let命令聲明變量之前, 該變量都是不可用的

let 不允許在相同作用域內(nèi)重復(fù)聲明同一個(gè)變量

可以使用let很方便的塊級(jí)作用域 (IIFE)


const

用來聲明常量,一旦聲明,其值不可修改(很多規(guī)則跟let一樣,理解成繼承吧)

必須一聲明就立即初始化,不能留到以后賦值

對(duì)于復(fù)雜的數(shù)據(jù)結(jié)構(gòu)(對(duì)象,數(shù)組), const只能保證保存該數(shù)據(jù)的地址不發(fā)生變化,不能保證其內(nèi)部值發(fā)生變化。(可以使用Object.freeze()凍結(jié)對(duì)象)


變量的解構(gòu)賦值

解構(gòu): ES6按照一定模式,從數(shù)組和對(duì)象中提取值,對(duì)變量進(jìn)行賦值,這稱為解構(gòu)

數(shù)組

var [a,b,c] = [1,2,3]; //a=1,b=2,c=3

var [head,,third,...tail]=[1,2,3,4]; //tail=[4]

var [foo] = [];//如果解構(gòu)不成功,變量的值就等于undefined

let [a,[b],d] = [1,[2,3],4]; //b=2;不完全解構(gòu),解構(gòu)依然可以成功

如果等號(hào)右邊不是數(shù)組(可遍歷的結(jié)構(gòu))就會(huì)報(bào)錯(cuò);

默認(rèn)值:

let [x,y=1] = [0]; //x=0,y=1;

let [x,y=1,z] = [0, undefined,2]; //x=0,y=1,z=2;(必須使用undefined/,因?yàn)閑s6內(nèi)部使用嚴(yán)格等===)

惰性求值, 如果默認(rèn)值是表達(dá)式, 只用用的時(shí)候才求值

對(duì)象

對(duì)象沒有次序,變量必須和屬性同名或使用以下方式,才能取得正確的值

var {foo:baz} = {foo: 1, bar: 2}; //baz=1;

字符串

因?yàn)樽址詭ength屬性,

let {length: len} = 'jifag';

字符串被轉(zhuǎn)換為類似數(shù)組的對(duì)象

const [a,b,c,d,e] = 'hello'; //a='h',b='e'...

解構(gòu)可以嵌套

var {p: [x,{y}]} = {p:['hello',{y:'world'}]}; // x='hello',y='world';此時(shí)p是模式不是變量名

函數(shù)參數(shù)的解構(gòu)賦值

酷!

圓括號(hào)問題

對(duì)于編譯器來說, 一個(gè)式子是模式還是表達(dá)式,沒有辦法從一開始就知道,帶來的問題就是, 如果模式中出現(xiàn)圓括號(hào)怎么處理。

建議: 不要在模式中放圓括號(hào)

幾種情況下在模式中使用圓括號(hào)會(huì)報(bào)錯(cuò)

用途?。。?!

交換變量的值 [x,y] = [y,x];

獲取從函數(shù)返回的多個(gè)值 var [a,b,c] = test(); //test return [1,2,3];

函數(shù)參數(shù)的定義

eg1: 參數(shù)是有序值function f([x,y,z]){}; f([1,2,3])

eg2: 參數(shù)是無序值function f({x,y,z}){}; f({x:1,y:2,z=3})

提取json數(shù)據(jù)

函數(shù)參數(shù)的默認(rèn)值(好用!?。。?/p>

let {log, sin, cos} = Math; //很方便就能把想用的拿出來


reg

u修飾符: 用于處理4個(gè)字節(jié)的utf=16編碼, 如(根本打不出來, 瀏覽器跟markdown也顯示不了好伐, 這個(gè)問題忽略)

y修飾符: ‘粘連’ 跟g一樣是全局匹配, 但g是從上一次匹配的剩余位置開始匹配,y限制了只能從剩余位置的第一位匹配

var str = 'aaa_aa_a', g = /a+/g, y = /a+/y;

g.exec(str); //執(zhí)行兩次, ['aaa'],['aa']

y.exec(str); //執(zhí)行兩次, ['aaa'],null


Array

() //將類數(shù)組(array like)對(duì)象和可遍歷的對(duì)象轉(zhuǎn)化為真正的數(shù)組,接受第二次參數(shù)類似于數(shù)組的map函數(shù)Array.from({'0':1, '1': 2, '2': 3}, x => x * x) //[1,4,9];

擴(kuò)展運(yùn)算符 (...)

Array.of() //將一組值轉(zhuǎn)化為數(shù)組 Array.of(1,2,3) //[1,2,3]

數(shù)組實(shí)例 Array.prototype.copyWithin(target, start = 0, end = this.length): 在數(shù)組內(nèi)部將指定位置的成員復(fù)制到其他位置(覆蓋)

數(shù)組實(shí)例 Array.prototype.find()和findIndex();

find(function(value, index, arr){})有點(diǎn)像filter, find只找到第一個(gè)符合條件的值就返回這個(gè)值 findIndex返回該值的位置

數(shù)組實(shí)例 Array.prototype.fill(value, start = 0, end = this.length) //很方便的初始化空數(shù)組,如果不是空數(shù)組, 數(shù)組中已有的元素將被重置 new Array(3).fill(0) //[0,0,0]

數(shù)組實(shí)例 Array.prototype.entries(),keys(),values() 返回遍歷器對(duì)象

數(shù)組實(shí)例 Array.includes() 返回布爾值

數(shù)據(jù)推導(dǎo) [for (year of years) if (year > 2000) year];


函數(shù)

rest參數(shù)(...變量名): 替代arguments function add(...value){}

擴(kuò)展運(yùn)算符(...) 像reset參數(shù)的逆運(yùn)算

console.log(...[1,2,3]) //1 2 3 (1,2,3)

替代數(shù)組的apply方法

合并數(shù)組 [1,2,...more] //more=[3,4];

與解構(gòu)賦值結(jié)合 const [first, ...rest] = [1,2,3,4];//first=1,rest=[2,3,4];

箭頭函數(shù)

var sum = (num1, num2) => num1 + num2;

如果函數(shù)內(nèi)代碼語句多于一行,要用大括號(hào)括起來,并使用return返回

簡(jiǎn)化回調(diào)函數(shù) [1,2,3].map(x => x * x); //[1,4,9]; [6,1,8].sort((a,b) => a - b); //[1,6,8]; const number = (...nums) => nums; // number(1,2,3)=>[1,2,3]


對(duì)象

屬性的簡(jiǎn)潔表示法 let obj = {x,test(){}}

屬性名表達(dá)式 let obj = {['a' + 'b']: 'ab'}

屬性名表達(dá)式與簡(jiǎn)潔表示法不能同時(shí)使用,會(huì)報(bào)錯(cuò)

Object.is()用來比較兩個(gè)值是否嚴(yán)格相等,與嚴(yán)格等(===)的行為基本一致,不同之處只有兩個(gè)

1. +0不等于-0

2. NaN等于自身

Object.assign(): 用來將源對(duì)象的所有可枚舉屬性賦值到目標(biāo)對(duì)象 //Object.assign(target, source1, source2);


Symbol

(研究了大半天終于發(fā)現(xiàn)意義在哪里,現(xiàn)在表示當(dāng)前對(duì)象的屬性有三種 obj.a、obj['a']、obj[a],一二種是ES5的字符串屬性名,第三種是Symbol類型,這樣就實(shí)現(xiàn)唯一的標(biāo)識(shí)了)

ES6引用一種新的原始數(shù)據(jù)類型Symbol表示獨(dú)一無二的值

let s = Symbol();typeof s;//symbol沒有‘new’

let s = Symbol('foo'),a={};a[s] = function(){};//不能使用點(diǎn)運(yùn)算符(a.s),不加引號(hào)(a['s']);

Symbol的參數(shù)是沒有實(shí)際意義的,只表示對(duì)Symbol實(shí)例的描述,主要是為了方便區(qū)分

symbol可以用來定義一組常量,保證這組常量的值都是不相等的

魔術(shù)字符串:在代碼之中多次出現(xiàn)、與代碼行程強(qiáng)耦合的某一個(gè)集體的字符串或數(shù)值。

消除魔術(shù)字符串的常用方便就是把它寫成一個(gè)常量, 此時(shí)比較適合用Symbol

Symbol類型的屬性名,不會(huì)出現(xiàn)在for...in、for...of遍歷中,也不會(huì)被Object.keys(),Object.getOwnPropertyNames()返回。也不是私有屬性。Object.getOwnPropertySymbols可以獲取指定對(duì)象的所有Symbol屬性名

Symbol.for(name):重新使用同一個(gè)symbol值

var s1 = Symbol.for('foo'), s2 = Symbol.for('foo');s1 === s2; //true

var s1 = Symbol('foo'), s2 = Symbol.for('foo');s1 === s2; //false

內(nèi)置的Symbol值


Proxy和Reflect

proxy用于修改某些操作的默認(rèn)行為,等同于在語言層面做出修改,屬于“元程序”(對(duì)編程語言進(jìn)行編程)。代理器,攔截器

作為構(gòu)造函數(shù)Proxy接受兩個(gè)參數(shù),第一個(gè)參數(shù)是所要代理的目標(biāo)對(duì)象,第二個(gè)參數(shù)是配置對(duì)象(包含有處理函數(shù)),要使Proxy起作用,必須針對(duì)Proxy實(shí)例進(jìn)行操作,而不是針對(duì)目標(biāo)對(duì)象

var proxy = new Proxy({},{

get: function(target, property){

return 35;

}

});

proxy.time; //35

set();利用Proxy,可以將讀取屬性的操作轉(zhuǎn)變?yōu)閳?zhí)行某個(gè)函數(shù),從而實(shí)現(xiàn)屬性的鏈?zhǔn)秸{(diào)用

var pipe = (function() {

var pipe;

return function(value) {

get: function(pipeObject, fnName) {

if(fnName == 'get') {

return pipe.reduce(function(val, fn) {

return fn(val);

}, value);

}

pipe.push(window[fnName]);

return pipeObject;

}

}

});

Proxy中設(shè)置set方法可以攔截某個(gè)屬性的賦值操作

let validator = {

set: function(obj, prop, value) {

if(prop === 'age'){

if(!Number.isInteger(value)) {

throw(new TypeError('The age is not an integer'));

}

if(value > 200) {

throw new RangeError('The age seems invalid');

}

}

obj[prop] = value;

}

}

let person = new Proxy({}, validator);

person.age = 100;

person.age = 400;//報(bào)錯(cuò)

apply()方法攔截函數(shù)的調(diào)用

has()方法可以隱藏某些屬性不被in操作符發(fā)現(xiàn)

construct()方法用來攔截new命令

deleteProperty()方法攔截delete操作

defineProperty()方法攔截Object.defineProperty();

enumerate()方法攔截for...in循環(huán)

ownKeys()方法攔截Object.keys()

Reflect 將Object某些語言層面的方法部署到Reflect之中


set

新的數(shù)據(jù)結(jié)構(gòu),類似于數(shù)組,成員的值都是唯一的,沒有重復(fù)的值

set函數(shù)可以接受一個(gè)數(shù)組(或類數(shù)組)let set = new Set([1,2,3,3]); [...set]; //[1,2,3]

屬性和方法set.prototype.size ,add(value), delete(value), has(value), clear()

遍歷操作 keys(),values(),entries(),forEach();前三個(gè)返回遍歷器。set結(jié)構(gòu)只有鍵值沒有鍵名,keys的返回值等于values

WeakSet 內(nèi)部成員只能是對(duì)象,不可遍歷,沒有clear方法,沒有size屬性,引用為存儲(chǔ)dom節(jié)點(diǎn),不必?fù)?dān)心這些節(jié)點(diǎn)從文檔移除時(shí)會(huì)引發(fā)內(nèi)存泄漏(沒有理解……)

Map

理解: Object提供“字符串——值”的對(duì)應(yīng),Map提供“值——值”的對(duì)應(yīng)

map接收一個(gè)數(shù)組作為參數(shù),數(shù)組的成員為一個(gè)個(gè)表示鍵值對(duì)的數(shù)組;

var map = new Map([['name', 'Jack'], ['age', '12']]);

map.size; //2

map.has('name'); //true

map.get('name'); //jack

map.set('gender', 'female'); //

map.delete('age');

map.clear();

WeakMap: 只接收對(duì)象為鍵名(null除外)。同樣應(yīng)用于dom, 部署私有屬性


Iterator

遍歷器,是一種接口,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的接口的訪問機(jī)制,任何數(shù)據(jù)結(jié)構(gòu)只要部署iterator接口就可以完成遍歷操作

不斷調(diào)用next方法 返回({value:value, done: Boolean})

for...of 循環(huán)

一個(gè)數(shù)據(jù)結(jié)構(gòu)只要具有Symbol.iterator屬性,就被認(rèn)為是可遍歷的。調(diào)用Symbol.iterator方法就可以得到當(dāng)前結(jié)構(gòu)的遍歷函數(shù)

以下三種結(jié)構(gòu)原生具有iterator接口: 數(shù)組, 某些類似數(shù)組的對(duì)象, set和map結(jié)構(gòu)

var map = new Map([['name', 'aya'], ['gender', 'female']]);

var iter1= map[Symbol.iterator]();

iter1.next(); // Object {"done": false,"value": Array ["name","aya"]}

//類數(shù)組調(diào)用Symbol.iterator

let iterable = {

'0': 1,

'1': 2,

'2': 3,

length: 3,

[Symbol.iterator]: Array.prototype[Symbol.iterator]

};

let ite =? iterable[Symbol.iterator]();

console.log(ite.next());

對(duì)象沒有默認(rèn)部署iterator接口,是因?yàn)槟膫€(gè)屬性先遍歷哪個(gè)后遍歷是不確定的。需要開發(fā)者手動(dòng)指定

// 為對(duì)象添加Iterator的一個(gè)實(shí)例

let obj = {

data: ['hello','world'],

[Symbol.iterator]() {

const self = this;

let index = 0;

return {

next() {

if(index < self.data.length) {

return {

value: self.data[index++],

done: false

};

}else {

return {

value: undefined,

done: true

};

}

}

}

}

}

for(let j of obj){

console.log(j);

}

var i = obj[Symbol.iterator]();

i.next(); //'hello';

調(diào)用Iterator接口的場(chǎng)合

1. 解構(gòu)賦值(會(huì)默認(rèn)調(diào)用Symbol.iterator方法)

2. 擴(kuò)展運(yùn)算符(...)

3. for...of,Array.from(),Map、Set、WeakMap、WeakSet,Promise.all(),Promise.race();

字符串可以訪問Sybmol.iterator方法

for...of(遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一方法)


Generator

概念: Generator是ES6提供的一種異步編程解決方案。狀態(tài)機(jī)。執(zhí)行Generator會(huì)返回一個(gè)遍歷器對(duì)象。

function與函數(shù)名之間有一個(gè)*號(hào), 函數(shù)內(nèi)部使用yield定義不同的內(nèi)部狀態(tài)

yeild就像是暫停標(biāo)志,generator.next()執(zhí)行一次就從就返回一個(gè){value:yeild語句后的值,done:},并暫停向下執(zhí)行,再執(zhí)行.next()方法再返回再暫停,直到遇到return語句為止,沒有return就放回{value: undefined, done: true};

yeild后面的表達(dá)式,只有當(dāng)調(diào)用next方法,內(nèi)部指針指向語句時(shí)才會(huì)執(zhí)行(惰性求值)

yeild語句不能出現(xiàn)在普通函數(shù)中(foreach改為使用for循環(huán)),yield語句如果在表達(dá)式中,必須加圓括號(hào)

next的參數(shù),會(huì)被當(dāng)做上一條yield語句的返回值

for...of,擴(kuò)展運(yùn)算符,解構(gòu)賦值,Array.from

應(yīng)用

1. 異步操作的同步化表達(dá): 處理異步操作,改寫回調(diào)函數(shù)

function* main(){

var result = yield request("http://some.url.com");

var resp = JSON.parse(result);

doSomething(resp);

}

2. 在任意對(duì)象上部署Iterator接口

function* iterEntries(obj) {

let keys = Object.keys(obj);

for(let i = 0; i < keys.length; i++) {

let key = keys[i];

yield [key, [obj[key]]];

}

}

let testObj = {hello: 'you', world: 'me'};

for(let [key,value] of iterEntries(testObj)){

console.log(key, value);

}

3. 作為數(shù)據(jù)結(jié)構(gòu)

function* doStuff(){

yield fs.readFile.bind(null, 'hello.txt');

yield fs.readFile.bind(null, 'work.txt');

yield fs.readFile.bind(null, 'as-so-on.txt');

}


Promise

一個(gè)對(duì)象,用來傳遞異步操作消息

有兩個(gè)特點(diǎn)

1. 對(duì)象的狀態(tài)不受外界干擾。Pending,Resolved(Fulfilled),Rejected。只有異步操作的結(jié)果可以決定當(dāng)前是哪一種狀態(tài)。

2. 一旦狀態(tài)改變就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果。promise只能從Pending變?yōu)镽esolved或Pending變成Rejected。只要一種變化發(fā)生就不會(huì)再發(fā)生變化

實(shí)例方法then, catch

Promise.all() 將多個(gè)Promise實(shí)例包裝成一個(gè)新的promise實(shí)例 promise.all([p1,p2,p3]);

Promise.race() 同樣將多個(gè)promise實(shí)例包裝成一個(gè)新的promise實(shí)例 promise.race([p1,p2,p3]);

區(qū)別: all方法,只有參數(shù)p全部變成resolved,p才為resolved(rejected同樣);race方法,只要有一個(gè)參數(shù)變成resolved,p就變?yōu)閞esolved(rejected同樣);

Promise.resolve() 將現(xiàn)有對(duì)象轉(zhuǎn)為promise對(duì)象

promise對(duì)象可以不帶參數(shù), 如果希望得到一個(gè)新的promise對(duì)象,可以直接調(diào)用 var p = Promise.resolve();

Promise.reject() 返回一個(gè)新的promise對(duì)象,狀態(tài)為Rejected

promise.done() 總是處于回調(diào)鏈的尾端,保證拋出任何可能出現(xiàn)的錯(cuò)誤

promise.finally() 跟promise.done最大的區(qū)別的是: finally接受普通函數(shù)作為參數(shù),無論如何都會(huì)執(zhí)行


異步操作

ES6的異步編程: 回調(diào)函數(shù),事件監(jiān)聽, 發(fā)布/訂閱, Promise對(duì)象

異步: 一個(gè)任何分為兩段,先執(zhí)行第一段,然后轉(zhuǎn)而這行其他認(rèn)識(shí),等做好準(zhǔn)備再回頭執(zhí)行第二段(不連續(xù)的操作)

Thunk函數(shù): 編譯器的傳名調(diào)用(如var m = 1; f(m+1),//m+1在f內(nèi)用到才求值,而不是先求值再調(diào)用f(2)),實(shí)現(xiàn)往事先將函數(shù)放到一個(gè)臨時(shí)函數(shù)中,再將這個(gè)臨時(shí)函數(shù)傳入函數(shù)體。這個(gè)臨時(shí)函數(shù)就叫Thunk函數(shù)。

js是傳值調(diào)用(var m = 1; f(m+1);// 先求值等于2,在調(diào)用f(2);Thunk函數(shù)替換的不是表達(dá)式而是多參數(shù)函數(shù),替換為單參數(shù)版本,且只接受回調(diào)函數(shù)作為參數(shù)。


Class基本語法

class Point{

constructor(x, y) {

this.x = x;

this.y =y;

}

toString(){

return "x+y= " + this.x + this.y;

}

}

語法糖

類的內(nèi)部定義的所有方法都是不可枚舉的(跟ES5不同)

constructor方法是類的默認(rèn)方法,new之后自動(dòng)調(diào)用該函數(shù)

如果忘記加new調(diào)用Class,會(huì)報(bào)錯(cuò)

Class表達(dá)式

const MyClass = class Me {

getClassName(){

return Me.name;

}

}

調(diào)用時(shí)使用new MyClass();Me只供Class的內(nèi)部代碼使用

不存在變量提升

代碼內(nèi)部為嚴(yán)格模式

extends 實(shí)現(xiàn)繼承

class ColorPoint extends Point {

constructor(x, y, color) {

super(x, y);

this.color = color;

}

}

super: 關(guān)鍵字,指代了父類的實(shí)例(即父類的this對(duì)象)

子類必須在constructor方法中調(diào)用super, 否則新建實(shí)例時(shí)會(huì)報(bào)錯(cuò)。因?yàn)槿绻徽{(diào)用super方法,子類就得不到this對(duì)象

父類只要用prototype就能被子類繼承, 父類可以是任意函數(shù)

對(duì)象總是繼承其他對(duì)象的,所以可以再任意一個(gè)對(duì)象中使用super關(guān)鍵字

static 靜態(tài)方法:在方法前面添加static關(guān)鍵字,不會(huì)被實(shí)例繼承,通過類直接調(diào)用

Class只有靜態(tài)方法沒有靜態(tài)屬性

new.target屬性: 返回new命令所作用的構(gòu)造函數(shù)(在構(gòu)造函數(shù)中使用)


修飾器

類的修飾(Class)

1. 修飾器是一個(gè)表達(dá)式,用于修改類的行為

2. 修飾器本質(zhì)是能在編譯時(shí)執(zhí)行的函數(shù)

3. 修飾器函數(shù)可以接受3個(gè)參數(shù): 目標(biāo)函數(shù)(必要),屬性名,該屬性的描述對(duì)象

方法的修飾(Class 內(nèi)部方法)

不能用于普通的函數(shù)(因?yàn)楹瘮?shù)提升)

@autobind @override @deprecate


Module

Class只是語法糖,并沒有解決模塊化問題

Module應(yīng)對(duì)大型程序


編碼風(fēng)格

塊級(jí)作用域let代替var

全局變量應(yīng)該只能設(shè)置常量,優(yōu)先使用const

靜態(tài)字符串使用單引號(hào)或反引號(hào),動(dòng)態(tài)字符串使用反引號(hào)(`)

解構(gòu)賦值


使用數(shù)組成語對(duì)變量賦值,優(yōu)先使用解構(gòu)賦值

函數(shù)的參數(shù)如果是對(duì)象的成員,優(yōu)先使用解構(gòu)賦值

如果函數(shù)返回多個(gè)值,優(yōu)先使用對(duì)象的解構(gòu)賦值而不是數(shù)組的解構(gòu)賦值(便于調(diào)整順序)

對(duì)象

單行定義的對(duì)象,最后一個(gè)成員不以逗號(hào)結(jié)尾;多行定義的對(duì)象,最后一個(gè)成員使用逗號(hào)結(jié)尾

對(duì)象盡量靜態(tài)化,如果屬性不可避免要添加,使用Object.assign()方法

如果對(duì)象的屬性名是動(dòng)態(tài)的,創(chuàng)建對(duì)象時(shí)使用屬性表達(dá)式定義

使用擴(kuò)展運(yùn)算符(...)復(fù)制數(shù)組

函數(shù)

立即執(zhí)行函數(shù)可以寫成箭頭函數(shù)的形式

(() => {

doSomething();

});

使用函數(shù)表達(dá)式的場(chǎng)合盡量用箭頭函數(shù)代替(綁定了this)

簡(jiǎn)單的單行的不會(huì)復(fù)用的函數(shù)用箭頭函數(shù)

所有的配置項(xiàng)都應(yīng)該幾種在一個(gè)對(duì)象,放在最后一個(gè)參數(shù),布爾值不可以直接作為參數(shù)

總是使用Class代替需要prototype的操作(class寫法更簡(jiǎn)潔)

使用extends實(shí)現(xiàn)繼承

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容