日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

大家好,我是Echa。

上個(gè)月有部分前端友友私信小編咨詢 JAVAScript 中 Symbol 怎么使用的呢?在哪些應(yīng)用場景下會(huì)用到這個(gè)Symbol?有哪些內(nèi)置屬性?等等。問的問題五花八門,今天無意中翻到《JavaScript 權(quán)威指南》這本書集中有幾頁詳細(xì)解讀——Symbol 。

 

所以小編決定出一期關(guān)于Symbol 讀后感的文章來深入解讀它。閑話少說,直接進(jìn)入主題。

全文大綱

  1. Symbol 前身
  2. Symbol 介紹
  3. Symbol 使用注意事項(xiàng)
  4. Symbol 的應(yīng)用場景
  5. Symbol 名下哪些屬性?

Symbol 前身

ES5的對象屬性名都是字符串,這很容易造成屬性名的沖突。 比如,你使用了一個(gè)他人提供的對象,但又想為這個(gè)對象添加新的方法,新方法的名字就有可能與現(xiàn)有方法產(chǎn)生沖突。如果有一種機(jī)制,保證每個(gè)屬性的名字都是獨(dú)一無二的就好了,這樣就從根本上防止屬性名的沖突。這就是ES6引入的Symbol的原因。

ES6引入了一種新的原始數(shù)據(jù)類型Symbol,表示獨(dú)一無二的值。它是JavaScript語言的第七種數(shù)據(jù)類型,前六種是:undefined、null、布爾值(Boolean)、字符串(String)、數(shù)值(Number)、對象(Object)。

Symbol值通過Symbol函數(shù)生成。這就是說,對象的屬性名現(xiàn)在可以有兩種類型,一種是原來就有的字符串,另一種就是新增的Symbol類型。凡是屬性名屬于Symbol類型,就都是獨(dú)一無二的,可以保證不會(huì)與其他屬性名產(chǎn)生沖突。

在JavaScript誕生之初,對象屬性只能使用字符串作為鍵,這導(dǎo)致了一些問題。例如,當(dāng)兩個(gè)不同的對象試圖使用相同的字符串作為屬性名時(shí),可能會(huì)導(dǎo)致屬性名沖突。此外,JavaScript中沒有一種簡單的方法來實(shí)現(xiàn)私有屬性或方法。

其實(shí)對于Symbol的追溯早在Lisp語言中就有體現(xiàn):

(setq e (intern "echa-symbol"))

這里其實(shí)就是創(chuàng)建了一個(gè)名為 echa-symbol 的符號對象,并將其賦值給變量e。

另外,ES6引入Symbol其實(shí)離不開Ruby的身影,在Ruby中,可以使用冒號(:)來創(chuàng)建符號。冒號后面跟著符號的名稱,如:

:echa-symbol

可以看到其實(shí)Ruby的語法更加簡潔,定義和使用都是用冒號區(qū)分:

person = {
  'name' => 'Echa',
  'age' => 35,
  :gender => 'Male'
}
puts person[:gender]  # 輸出:'Male'

所以,在這樣的需求背景下,ES6在首批特性中包含了Symbol也不足為奇了。

Symbol 介紹

Symbol是ES6中新增的一種原始數(shù)據(jù)類型, 被劃分到了基本數(shù)據(jù)類型中基本數(shù)據(jù)類型: 字符串、數(shù)值、布爾、undefined、null、Symbol 引用數(shù)據(jù)類型: Object。

例如 number, boolean或者null,它們通常用于避免屬性名稱沖突,或模擬 JavaScript 對象的私有值。

您可以通過調(diào)用全局函數(shù)來創(chuàng)建 Symbol():

const sym = Symbol();

Symbol() 函數(shù)接受一個(gè)參數(shù),一個(gè)字符串 description 打印 Symbols 時(shí)會(huì)顯示。

const sym = Symbol('my description');
console.log(sym); 
// Prints "Symbol(my description)"

主要特征

Symbols 有兩個(gè)關(guān)鍵特征。

第一個(gè)關(guān)鍵特征是 沒有兩個(gè) Symbols 永遠(yuǎn)相等 。 即使兩個(gè) Symbols 具有相同的描述,它們也不相等。

let s1 = Symbol('foo');
let s2 = Symbol('foo');

console.log(s1 === s2)
//false

第二個(gè)關(guān)鍵特性是 對象鍵可以是 Symbols。通常對象鍵只能是 Symbols 或字符串。

const test = Symbol('test');
const obj = {};
obj.test = 'hello';
obj[test] = 'world';
obj.test;
// 'hello'obj[test];
// 'world'

由于沒有兩個(gè) Symbols 永遠(yuǎn)相等,因此除非您有權(quán)訪問 Symbols,否則您無法訪問 Symbols 屬性。 這使得 Symbols 可以方便地創(chuàng)建只能在特定函數(shù)中訪問的隱藏值。

function addSymbol(obj) {  
  const sym = Symbol('test'); 
  obj[sym] = 'my hidden value'; 
  return obj;
}
const obj = addSymbol({});
// No way to access obj[sym] here, unless you explicitly look
// into `Object.getOwnPropertySymbols()`.

Symbols 也被排除在外JSON.stringify()輸出,這使得它們非常適合存儲(chǔ)最終用戶不應(yīng)該看到的純程序數(shù)據(jù)。

Symbol 值最顯著的用途是作為對象屬性的 key。而 ES6 之前,屬性的 key 只能是字符串(否則也會(huì)發(fā)生自動(dòng)類型轉(zhuǎn)換)。key 為 Symbol 值的屬性無法使用點(diǎn)號(.)訪問,只能使用中括號([])。類似地,在對象字面值或類定義中,添加 key 為 Symbol 值的屬性需要借助計(jì)算屬性名的語法,如:

const MY_KEY = Symbol();
const FOO = Symbol();
let obj = {
    [MY_KEY]: 123,
    [FOO]() {
        return 'bar';
    }
}; 

JavaScript 模塊化后,在模塊中創(chuàng)建 Symbol 值并用作對象屬性 key,模塊作者可以自信地認(rèn)為該屬性不會(huì)覆寫對象上已有的屬性。類似道理,如果模塊中使用了 Symbol key 的對象屬性,只要不把 Symbol 值導(dǎo)出,就可以確信其他模塊不會(huì)不經(jīng)意地覆寫該屬性。

對于應(yīng)用開發(fā)者,Symbol 可以有這樣的使用場景:你從某第三方代碼獲得了一個(gè)對象,你想在該對象上存儲(chǔ)自己的屬性,但該第三方代碼是不透明的,或者不受你控制,所以你無從得知第三方代碼會(huì)在該對象上設(shè)置什么屬性,此時(shí)就可以使用 Symbol key 屬性,既能確信不會(huì)和已有屬性沖突,也能確信第三方代碼不會(huì)意外地修改你設(shè)置的屬性:

const extension = Symbol('my extension symbol');
let o = {
    [extension]: {/* 將擴(kuò)展數(shù)據(jù)存儲(chǔ)于該對象*/}
};
o[extension].x = 0; // 無論怎樣都不可能和 o 的其他屬性產(chǎn)生沖突。

以上場景還可表述為給對象關(guān)聯(lián)一個(gè)值,但存儲(chǔ)關(guān)聯(lián)值的鍵名希望從機(jī)制上防止和其他屬性名沖突。另外也可用 WeakMap 存儲(chǔ)對象到其關(guān)聯(lián)值的映射,兩種方法的異曲同工之處是:當(dāng)對象本身消亡時(shí),該映射關(guān)系也隨之消亡。

然而,必須知道的是,Symbol key 屬性并不是一種安全機(jī)制,第三方代碼仍然可以調(diào)用
Object.getOwnPropertySymbols(o) 獲得對象上的 Symbol key 屬性,改變屬性值,但此時(shí)就是第三方庫有意為之,而不是不經(jīng)意的行為了,但這應(yīng)該會(huì)在其文檔上有所提及才對。

Symbol 使用注意事項(xiàng)

  • Symbol是基本數(shù)據(jù)類型!!!!不要加new哦
  • 后面括號可以傳入一個(gè)字符串,只是一個(gè)標(biāo)記,方便我們閱讀,沒有任何意義
  • 類型轉(zhuǎn)化的時(shí)候不可轉(zhuǎn)化為數(shù)值
//只能轉(zhuǎn)化為字符串和布爾值
console.log(String(name));
console.log(Boolean(name));
console.log(Number(name))
  • 不能做任何運(yùn)算
let name=Symbol('Echa');
console.log(name+111)
console.log(name+'ccc')
//全部報(bào)錯(cuò)
  • symbol生成的值作為屬性或者方法的時(shí)候,一定要保存下來,否則后續(xù)無法使用
let name=Symbol('name');
let obj={
  // name:'lnj',
    [Symbol('name')]:'lbj'
}
console.log(obj.name);  
//訪問不到,因?yàn)? [Symbol('name')]又是一個(gè)新的值,和上面的name不是同一個(gè)
  • for循環(huán)遍歷對象的時(shí)候是無法遍歷出symbol的屬性和方法的 Object.getOwnPropertySymbols()
et name=Symbol('name');
let obj={
  [name]:'lnj',
    age:12,
    teacher:'wyx'
}
for(let key in obj){
    console.log(key)   //只能打印出age和teacher
}
//這個(gè)方法可以單獨(dú)取出Symbol(name)
console.log(Object.getOwnPropertySymbols(obj))

 

Symbol 的應(yīng)用場景

  • 在企業(yè)開發(fā)中如果需要對一些第三方的插件、框架進(jìn)行自定義的時(shí)候可能會(huì)因?yàn)樘砑恿送膶傩曰蛘叻椒? 將框架中原有的屬性或者方法覆蓋掉為了避免這種情況的發(fā)生, 框架的作者或者我們就可以使用Symbol作為屬性或者方法的名稱。
  • 消除魔術(shù)字符串

魔術(shù)字符串:在代碼之中多次出現(xiàn)、與代碼形成強(qiáng)耦合的某一個(gè)具體的字符串或者數(shù)值。風(fēng)格良好的代碼,應(yīng)該盡量消除魔術(shù)字符串,改由含義清晰的變量代替。

const gender = {
   //這樣就說明man就是一個(gè)獨(dú)一無二的值,不用再man:'man'   
    man: Symbol(),
    woman: Symbol(),
}
function isMan(gender) {
    switch (gender) {
        case gender.man:
            console.log('男性');
            break;
        case gender.woman:
            console.log('女性');
            break
    }
}
isMan(gender.man)  //男性
  • 為對象定義一些非私有的、但又希望只用于內(nèi)部的方法。

由于以 Symbol 值作為鍵名,不會(huì)被常規(guī)方法遍歷得到。我們可以利用這個(gè)特性,為對象定義一些非私有的、但又希望只用于內(nèi)部的方法。

注意:symbol并不能實(shí)現(xiàn)真正的私有變量的效果,只是不能通過常規(guī)的遍歷方法拿到symbol類型的屬性而已

再來復(fù)習(xí)一下對象的遍歷方法

  1. for (let xx in obj) :i代表key
  2. for (let xx of obj):不是自帶的哈
  3. Object.keys(obj) :返回包含key的數(shù)組
  4. Object.values(obj) :返回包含value的數(shù)組
  5. Object.getOwnPropertyNames() :返回包含key的數(shù)組

上述的所有方法都是遍歷不到symbol類型的(注意,是遍歷時(shí)取不到symbol,并不是說我們訪問不到對象的symbol類型)

可以遍歷到symbol的方法:


Object.getOwnPropertySymbols() :返回對象中只包含symbol類型key的數(shù)組

Reflect.ownKeys() :返回對象中所有類型key的數(shù)組(包含symbol)

let _password = Symbol('password')
const obj = {
    name: 'Echa',
    gender: 'male',
    [_password]: '123456'
}
for (let item in obj) {
    console.log(item);
}
console.log(Object.keys(obj));
console.log(Object.values(obj));
console.log(Object.getOwnPropertyNames(obj));
console.log(Object.getOwnPropertySymbols(obj));
console.log(Reflect.ownKeys(obj))
// 輸出123456,所以還是可以直接訪問到symbol類型的屬性,
//所以symbol并不能真正實(shí)現(xiàn)私有變量的設(shè)定,
//所以一般只用于定義一些非私有的、但又希望只用于內(nèi)部的方法
console.log(obj[_password]);

Symbol 名下哪些屬性?

在 JavaScript 中,Symbol 是一種非常特殊的數(shù)據(jù)類型,可以用來表示獨(dú)一無二的值。每個(gè) Symbol 值都是唯一的,一般可以作為對象屬性的標(biāo)識符使用,這些屬性稱為 Symbol 屬性,它們不會(huì)與其他屬性產(chǎn)生命名沖突,所以可以用于實(shí)現(xiàn)一些高級特性和語言擴(kuò)展。

Symbol 還有一些內(nèi)置屬性,比如 Symbol.iterator、Symbol.toPrimitive 和 Symbol.toStringTag 等,它們在實(shí)現(xiàn)一些特殊的需求(比如自定義對象的迭代、類型轉(zhuǎn)換和字符串描述時(shí))非常有用,今天我們就來一起看一下 Symbol 內(nèi)置屬性的一些妙用,看看你知道幾個(gè)?

Symbol.iterator

Symbol.iterator 可以讓我們定義一個(gè)對象默認(rèn)的迭代器。

有什么用途呢?正常的對象一般都是不可迭代的,如果我們直接用 for of 遍歷一個(gè)對象,會(huì)拋出異常:TypeError: obj is not iterable ,因?yàn)閷ο竽J(rèn)是不可迭代的。

我們可以用 for in 來做遍歷:

const obj = { name: 'ConardLi', age: 17 };

for (const key in obj) {
  if (Object.hasOwnProperty.call(obj, key)) {
    const element = obj[key];
    console.log(key, element);
  }
}

但是如果我們開發(fā)的是一個(gè)自定義的數(shù)據(jù)結(jié)構(gòu),for in 可能就不那么好使了,比如現(xiàn)在有一個(gè)音樂播放器對象,我們需要實(shí)現(xiàn)一個(gè)自定義的播放列表,用于存儲(chǔ)用戶添加的歌曲。這個(gè)列表可以看作一個(gè)集合,其中每個(gè)元素代表一個(gè)歌曲,包含歌曲的名稱、作者、時(shí)長等屬性。

這時(shí)我們就可以通過定義 Symbol.iterator 方法,讓這個(gè)列表可以通過 for...of循環(huán)進(jìn)行遍歷:

class Song {
  constructor(name, artist, duration) {
    this.name = name;
    this.artist = artist;
    this.duration = duration;
  }
}

class Playlist {
  constructor() {
    this.songs = [];
  }

  addSong(song) {
    this.songs.push(song);
  }

  [Symbol.iterator]() {
    let index = 0;
    const songs = this.songs;
    return {
      next: () => ({
        value: songs[index++],
        done: index > songs.length
      })
    }
  }
}

const playlist = new Playlist();

playlist.addSong(new Song('Song 1', 'Artist 1', '3:45'));
playlist.addSong(new Song('Song 2', 'Artist 2', '4:20'));
playlist.addSong(new Song('Song 3', 'Artist 3', '5:10'));

for (const song of playlist) {
  console.log(song.name);
}

// 輸出:
// "Song 1"
// "Song 2"
// "Song 3"

Symbol.toStringTag

默認(rèn)情況下,我們在任何一個(gè)自定義的對象上調(diào)用 toString 方法,返回值都是下面這樣:

[object Object]

Symbol.toStringTag 可以被用來自定義對象的 toString 方法的返回值(注意不是重寫 toString 方法),這個(gè)特性在調(diào)試的時(shí)候非常有用,幫助開發(fā)者更方便地了解對象的類型信息:

class People {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  get [Symbol.toStringTag]() {
    return 'People';
  }
}

const people = new People('ConardLi', 17);

console.log(people.toString()); // [object People]

Symbol.toPrimitive

Symbol.toPrimitive 可以被用來自定義對象類型轉(zhuǎn)換時(shí)的行為。它可以接受一個(gè) hint 參數(shù),用于指示對象應(yīng)該被轉(zhuǎn)換成什么類型的值,比如 Number、String 或者其他默認(rèn)的值。

舉一個(gè)實(shí)際的應(yīng)用場景:假設(shè)我們正在開發(fā)一個(gè)日期處理工具,其中需要實(shí)現(xiàn)一個(gè)自定義的日期時(shí)間對象。這個(gè)對象包含日期時(shí)間的年月日時(shí)分秒等信息,這時(shí)候就可以用到 Symbol.toPrimitive 方法,來幫助我們自定義對象的類型轉(zhuǎn)換行為:

class MyDateTime {
  constructor(year, month, day, hour = 0, minute = 0, second = 0) {
    this._datetime = new Date(year, month - 1, day, hour, minute, second);
  }

  [Symbol.toPrimitive](hint) {
    switch (hint) {
      case 'number':
        return this._datetime.getTime();
      case 'string':
        return this._datetime.toLocaleString();
      default:
        return this._datetime.toString();
    }
  }
}

const myDate = new MyDateTime(2023, 4, 8, 15, 30, 0);

console.log(myDate); // 輸出:Sat Apr 08 2023 15:30:00 GMT+0800 (中國標(biāo)準(zhǔn)時(shí)間)
console.log(myDate + 10000); // 輸出:1699950200000
console.log(`${myDate}`); // 輸出:"2023/4/8 下午3:30:00"

Symbol.asyncIterator

Symbol.asyncIterator 可以用來實(shí)現(xiàn)一個(gè)對象的異步迭代器,它可以用于遍歷異步數(shù)據(jù)流,比如異步生成器函數(shù)、異步可迭代對象等。這個(gè)特性在我們需要處理異步數(shù)據(jù)流時(shí)非常有用。

舉一個(gè)實(shí)際的應(yīng)用場景:假設(shè)我們正在開發(fā)一個(gè)異步數(shù)據(jù)源處理器,其中包含了大量的異步數(shù)據(jù),比如網(wǎng)絡(luò)請求、數(shù)據(jù)庫查詢等。這些數(shù)據(jù)需要被逐個(gè)獲取并處理,同時(shí)由于數(shù)據(jù)量非常大,一次性獲取全部數(shù)據(jù)會(huì)導(dǎo)致內(nèi)存占用過大,因此需要使用異步迭代器來逐個(gè)獲取數(shù)據(jù)并進(jìn)行處理:

class AsyncDataSource {
  constructor(data) {
    this._data = data;
  }

  async *[Symbol.asyncIterator]() {
    for (const item of this._data) {
      const result = awAIt this._processAsyncData(item);
      yield result;
    }
  }

  async _processAsyncData(item) {
    // 模擬異步處理數(shù)據(jù)的過程
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(item.toUpperCase());
      }, Math.random() * 1000);
    });
  }
}

async function processData() {
  const dataSource = new AsyncDataSource(['a', 'b', 'c', 'd', 'e']);
  for await (const data of dataSource) {
    console.log(data);
  }
}

processData();

Symbol.hasInstance

Symbol.hasInstance可以用于確定一個(gè)對象是否是某個(gè)構(gòu)造函數(shù)的實(shí)例,它可以用來改變 instanceof 的行為:

class MyArray {
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}

const arr = [1, 2, 3];
console.log(arr instanceof MyArray); // true

Symbol.species

Symbol.species 可以用于指定創(chuàng)建派生對象時(shí)要使用的構(gòu)造函數(shù)。一個(gè)實(shí)際的需求場景可能是我們需要對一個(gè)類進(jìn)行繼承,并且希望這個(gè)類的某些方法返回一個(gè)新的派生對象而不是基類的實(shí)例對象。下面是一個(gè)簡單的例子:

class MyArray extends Array {
  static get [Symbol.species]() {
    return Array;
  }

  test(){
    console.log('test');
  }
}

const myArray = new MyArray(1, 2, 3);
const mAppedArray = myArray.map(x => x * 2);
myArray.test();

console.log(mappedArray instanceof MyArray); // false
console.log(mappedArray instanceof Array); // true

Symbol.match

Symbol.match 可以用來確定使用 String.prototype.match 方法時(shí)要搜索的值,它可用于更改 match 類 RegExp 對象的方法行為,下面是一個(gè)實(shí)際實(shí)用案例:

class CustomRegExp extends RegExp {
  [Symbol.match](str) {
    const matches = super[Symbol.match](str);
    if (matches) {
      return matches.map(match => {
        return `匹配到了: ${match}`;
      });
    }
    return matches;
  }
}

const regex = new CustomRegExp('hello', 'g');
const result = 'hello world'.match(regex);
console.log(result); // ["匹配到了: hello"]

Symbol.replace

Symbol.replace 可以幫我們更靈活的處理 String.prototype.replace 方法,比如我們可以自定義字符串的替換行為。

比如有這樣一個(gè)需求場景:我們有一個(gè)字符串處理庫,我們想自定義它的 replace 方法,讓它可以替換一個(gè)字符串的所有元音字母。這時(shí)候就可以用到 Symbol.replace :

const vowels = ['a', 'e', 'i', 'o', 'u'];

const customReplace = str => {
  let result = '';
  for (let i = 0; i < str.length; i++) {
    if (vowels.includes(str[i])) {
      result += '*';
    } else {
      result += str[i];
    }
  }
  return result;
};

const customString = {
  [Symbol.replace]: customReplace
};

const originalString = "hello world";

const result = originalString.replace(customString, '');

console.log(result); // outputs "h*ll* w*rld"

Symbol.split

Symbol.split 可以用來確定使用 String.prototype.split 方法執(zhí)行時(shí)具體要拆分的值。

一個(gè)實(shí)際需求場景:我們需要從文本中提取出所有的數(shù)字。但是文本中的數(shù)字可能包含在不同的字符和符號中,例如括號、分隔符和單位等。使用 Symbol.split 可以自定義分割符,這樣我們就可以根據(jù)自己的需求來對文本進(jìn)行分割。

const customSplit = str => str.split(/[s$¥€]+/);

const customRegExp = {
  [Symbol.split]: customSplit
};

const string = "100$200¥300€400 500";

console.log(string.split(customRegExp)); // outputs [ '100', '200', '300', '400', '500' ]

Symbol.unscopables

Symbol.unscopables 通常可以用來避免在使用 with 語句時(shí)訪問對象中不希望被訪問的屬性。下面是一個(gè)示例,其中使用 with 語句訪問對象的某些屬性,但通過將這些屬性添加到 [Symbol.unscopables] 對象中,可以防止訪問:

const globalVars = {
  a: 10,
  b: 20,
  [Symbol.unscopables]: {
    b: true
  }
};

with (globalVars) {
  console.log(a); // 輸出 10
  console.log(b); // 拋出 ReferenceError
}

最后

一臺電腦,一個(gè)鍵盤,盡情揮灑智慧的人生;幾行數(shù)字,幾個(gè)字母,認(rèn)真編寫生活的美好;

一 個(gè)靈感,一段程序,推動(dòng)科技進(jìn)步,促進(jìn)社會(huì)發(fā)展。

創(chuàng)作不易,喜歡的老鐵們加個(gè)關(guān)注,點(diǎn)個(gè)贊,打個(gè)賞,后面會(huì)不定期更新干貨和技術(shù)相關(guān)的資訊,速速收藏,謝謝!你們的一個(gè)小小舉動(dòng)就是對小編的認(rèn)可,更是創(chuàng)作的動(dòng)力。

分享到:
標(biāo)簽:JavaScript
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定