中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript?getter?setter金字塔???????怎么實現

發布時間:2022-08-17 16:30:10 來源:億速云 閱讀:149 作者:iii 欄目:開發技術

這篇文章主要介紹“JavaScript getter setter金字塔怎么實現”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“JavaScript getter setter金字塔怎么實現”文章能幫助大家解決問題。

    引言

    函數是JavaScript的基石。 它是一種靈活的、抽象的,可作為其他抽象的基礎, 如:Promise、Iterables、Observables等。 

    函數

    JavaScript的基礎是一級值,如: numbers、strings、objects、booleans等。 雖然,您可以只使用這些值和控制流(if/else/for等)來編寫程序,但很快您可能需要編寫一個新的函數來改進您的程序。

    JavaScript中必須通過函數進行抽象,像異步I/O操作等通常都必須使用callback回調函數。 JavaScript中的函數,與【函數式編程】中的純函數不同,建議最好將它們簡單理解為“流程”,因為它只得惰性的可重用代碼塊,具有可選的輸入(參數)和可選的輸出(返回值)

    與硬編碼相比,函數有以下幾個重要的好處:

    • 懶惰/可重用性, 函數內的代碼必須是惰性的(即除非被調用,否則不會執行)才能使其可重用

    • 實現的靈活性,函數的使用者并不關心函數內部是如何實現的,這意味著可以各種方式靈活的實現函數。

    getters

    getter是一種不用傳遞任何參數但需要有返回值的函數。
    函數定義: () => X

    JavaScript?getter?setter金字塔???????怎么實現

    getter是一種不用傳遞任何參數但需要有返回值的函數。 JavaScript中有許多這樣的getter, 例如: Math.random()、Date.now()等

    getter作為值的抽象也很有用,例如:user 與 getUser

    const user = {name: 'Alice', age:30};
    console.log(user.name); // Alice
    function getUser(){
    	return {name: 'Alice', age:30};
    }
    console.log(getUser().name); // Alice

    通過使用getter, 我們可以利用函數的一個好處: 惰性. 即我們不調用 getUser()user對象就不會被白白創建。 同時,我們利用了函數的另一好處:實現的靈活性, 因為我們可以通過多種不同的方式來返回對象。

    getter還允許我們對副作用有一個鉤子,當執行getter時,我們可以觸發有用的副作用函數,比如console.log輸出日志 或是 觸發Analytics事件等,例如:

    function getUser(){
    	Analytics.sendEvent('User object is now being accessed');
    	return {name:'Alice', age:30};
    }

    getter上的計算,也是可以抽象的。例如:

    function add(getX, getY){
    	return function getZ(){
    		const x = getX();
    		const y = getY();
    		return x + y;
    	}
    }

    當getter返回不可預測的值時,這種抽象計算的好處更加明顯,例如:使用getter添加Math.random:

    const getTen = () => 10;
    const getTenPlusRandom = add(getTen, Math.random);
    
    console.log(getTenPlusRandom()); // 10.948117215055046
    console.log(getTenPlusRandom()); // 10.796721274448556
    console.log(getTenPlusRandom()); // 10.15350303918338
    console.log(getTenPlusRandom()); // 10.829703269933633

    比較常見的是getter與Promise一起搭配使用,因為Promise是不可重用的計算,因此,將Promise的構造函數包裝在一個getter中(如我們熟知的"工廠函數"或"thunk")使其可重用。

    setters

    setters是有一個或多個輸入參數,但沒有返回值的函數。
    函數定義: X => ()

    JavaScript?getter?setter金字塔???????怎么實現

    setters是有一個或多個輸入參數,但沒有返回值的函數。 在JavaScript運行時或DOM中有許多這樣的setters, 比如: console.log(x), document.write(x)等。

    與getter不同,setter通常不用抽象。 因為函數沒有返回值,這意味著函數僅用于發送數據或執行JavaScript命令等。 例如, 上文中的getter getTen是數字10的抽象,我們可以將它作為值進行傳遞,但如果將函數setTen作為值傳遞是沒有意義的,因為它沒有返回值。

    換句話說,setter可以是其他setter的簡單包裝器。例如:簡單包裝下setter console.log:

    function fancyConsoleLog(str) {
      console.log('? ' + str + ' ?');
    }

    getter-getters

    getter-getters是一種不需要輸入參數且返回一個getter的函數。
    函數定義: () => (() => X)

    JavaScript?getter?setter金字塔???????怎么實現

    “getter-getter”: 一種特殊類型的getter,其返回值是一個getter.

    對getter的原始需求是使用getter的返回值進行迭代。
    例如,我們想顯示二次冪的數字序列,我們可以使用getter getNextPowerOfTwo()

    let i = 2;
    function getNextPowerOfTwo() {
      const next = i;
      i = i * 2;
      return next;
    }
    console.log(getNextPowerOfTwo()); // 2
    console.log(getNextPowerOfTwo()); // 4
    console.log(getNextPowerOfTwo()); // 8
    console.log(getNextPowerOfTwo()); // 16
    console.log(getNextPowerOfTwo()); // 32
    console.log(getNextPowerOfTwo()); // 64
    console.log(getNextPowerOfTwo()); // 128

    在上面示例代碼中,變量i是全局聲明的,若我們想重新迭代序列,則必須要重置變量i, 從而泄漏了getter的實現細節。

    若想將上述代碼變為可重用且不包含全局變量,我們需要將getter封裝在另一個函數中,這個包裝函數也是一個getter.

    function getGetNext() {
      let i = 2;
      return function getNext() {
        const next = i;
        i = i * 2;
        return next;
      }
    }
    
    let getNext = getGetNext();
    console.log(getNext()); // 2
    console.log(getNext()); // 4
    console.log(getNext()); // 8
    getNext = getGetNext(); // ???? restart!
    console.log(getNext()); // 2
    console.log(getNext()); // 4
    console.log(getNext()); // 8
    console.log(getNext()); // 16
    console.log(getNext()); // 32

    可以看出,getter-getter是一種特殊類型的getter, 它繼承了getter的所有優點,例如:

    • 實現的靈活性

    • 用于副作用的鉤子(hook)

    • 惰性,其惰性體現在函數在初始化時,外部函數啟用延遲初始化,而內部函數啟用值時延遲初始化。

    function getGetNext() {
      // ???? LAZY INITIALIZATION
      let i = 2;
    
      return function getNext() {
        // ???? LAZY ITERATION
        const next = i;
        i = i * 2;
        return next;
      }
    }

    setter-setter

    setter-setter是一種以setter作為輸入且無返回值的函數。 函數定義: (X => ()) => ()

    JavaScript?getter?setter金字塔???????怎么實現

    setter-setter是一種特殊的setter函數,其中傳遞的參數也是setter。雖然基本的setter不是抽象函數,但setter-setter是能夠表示可在代碼庫中傳遞的值的抽象。 例如下列中,通過這個setter來表示數字10:

    function setSetTen(setTen) {
      setTen(10)
    }

    注意: setter沒有返回值。

    通過簡單地重構,讓上述示例代碼的可讀性更強:

    function setTenListener(cb) {
      cb(10)
    }

    cb,即callback縮寫,名為“回調”,它表明在JavaScript中如何使用setter-setter

    在JavaScript中,有大量回調的案例。 顧名思義,cb代表“回調”,通過上述示例代碼來說明,cb在setter-setter如何使用。

    下面兩個示例,在功能上是等價的,但是調用方式不同。

    setSetTen(console.log);
    
    // compare with...
    
    console.log(getTen());

    setter-setter具有與getter-getter相同的好處:

    • 實現的靈活性

    • 用于副作用的鉤子(hook)

    • 惰性,其惰性體現在函數在初始化時,外部函數啟用延遲初始化,而內部函數啟用值時延遲初始化。

    同時,它還有兩個getter-getter所沒有的新特性:

    • 控制反轉

    • 異步性

    在上面的示例中,使用getter的代碼指示何時使用“console.log”使用getter。
    然而,當使用setter-setter時,setter-seter本身決定何時調用“console.log”。 這種控制反轉允許setter-setter擁有比getter更大的能力,例如通過向回調函數傳遞許多值, 例如:

    function setSetTen(setTen) {
      setTen(10)
      setTen(10)
      setTen(10)
      setTen(10)
    }

    控制反轉還可以使setter決定何時向回調傳遞值,例如: 異步傳遞。 試想一下,若將“setSetTen”的更換為“setTenListener”呢?

    function setTenListener(cb) {
      setTimeout(() => { cb(10); }, 1000);
    }

    setter-setter在JavaScript異步編程中的很常見,但回調函數不一定是異步的。
    例如,下面的“setSetTen”示例中,它是同步的:

    function setSetTen(setTen) {
      setTen(10)
    }
    
    console.log('before');
    setSetTen(console.log);
    console.log('after');
    
    // (Log shows:)
    // before
    // 10
    // after

    iterables

    iterable是省略了實現細節的getter-getter, 其返回值是一個描述型的對象值或完成時的對象。

    An iterable is (with some details omitted:) a getter-getter of an object that describes either a value or completion

    函數定義: () => (() => ({done, value}))

    getter-getter可以重啟序列值,但它沒有通知序列何時結束的約定。
    Iterables是一種特殊的getter-getter,它的返回值中始終有2個屬性對象:

    • done,布爾值,表示是否完成

    • value,任意值,實際傳遞的值(在done的值不為true時)

    完成指示符done,能夠使iterable的代碼在執行時,知道后續GET將返回無效數據,因此iterable知道何時停止迭代。
    在下面的示例中,我們可以根據完成指示符生成一個偶數范圍為40到48的有限序列:

    function getGetNext() {
      let i = 40;
      return function getNext() {
        if (i <= 48) {
          const next = i;
          i += 2;
          return {done: false, value: next};
        } else {
          return {done: true};
        }
      }
    }
    
    let getNext = getGetNext();
    for (let result = getNext(); !result.done; result = getNext()) {
      console.log(result.value);
    }

    ES6 Iterables除了簡單的() => (() => ({done, value}))模式之外,還有更多的約定。它們在每個getter上添加了一個包裝器對象:

    • 外部getter包含對象:{[Symbol.iterator]:f}

    • 內部getter包含對象: {next:g}

    以下是與上一個示例代碼功能等價的ES6 Iterable代碼:

    const oddNums = {
      [Symbol.iterator]: () => {
        let i = 40;
        return {
          next: () => {
            if (i <= 48) {
              const next = i;
              i += 2;
              return {done: false, value: next};
            } else {
              return {done: true};
            }
          }
        }
      }
    }
    let iterator = oddNums[Symbol.iterator]();
    for (let result = iterator.next(); !result.done; result = iterator.next()) {
      console.log(result.value);
    }

    注意,兩個示例間實現的差異點:

    -function getGetNext() {
    +const oddNums = {
    +  [Symbol.iterator]: () => {
         let i = 40;
    -  return function getNext() {
    +    return {
    +      next: () => {
             if (i <= 48) {
               const next = i;
               i += 2;
               return {done: false, value: next};
             } else {
               return {done: true};
             }
           }
    +    }
       }
    +}
    
    -let getNext = getGetNext();
    -for (let result = getNext(); !result.done; result = getNext()) {
    +let iterator = oddNums[Symbol.iterator]();
    +for (let result = iterator.next(); !result.done; result = iterator.next()) {
      console.log(result.value);
    }

    ES6提供了語法糖for let以便快速迭代對象:

    for (let x of oddNums) {
      console.log(x);
    }

    為了方便創建Iterables,ES6還提供了生成器函數語法糖 function*

    function* oddNums() {
      let i = 40;
      while (true) {
        if (i <= 48) {
          const next = i;
          i += 2;
          yield next;
        } else {
          return;
        }
      }
    }

    使用生產端語法糖和**消費端語法糖*,自2015年以來,可迭代函數是JavaScript中可完成值序列的易于使用的抽象。請注意,調用生成器函數將返回可迭代函數,生成器函數本身不是可迭代函數:

    自2015年后,更易于使用iterables來抽象可序列化對象值。 需要注意的是,調用生成器函數將返回一個可迭代對象,生成器函數本身不可迭代。

    function* oddNums() {
      let i = 40;
      while (true) {
        if (i <= 48) {
          yield i;
          i += 2;
        } else {
          return;
        }
      }
    }
    
    for (let x of oddNums()) {
      console.log(x);
    }

    promises

    Promise是一個(省略了一些細節)特殊的setter, 它包含2個setter, 并且還有額外的保障。
    函數定義: (X => (), Err => ()) => ()

    JavaScript?getter?setter金字塔???????怎么實現

    雖然setter-setter功能強大,但由于控制反轉,它們可能變得非常不可預測。

    • 它們可以是同步或異步的

    • 也可以隨時間傳遞零或一個或多個值。

    Promise是一種特殊的setter,它為返回值提供一些特殊的保證:

    • 內部setter(“回調”)從不同步調用

    • 內部setter最多調用一次

    • 提供了一個可選的第二setter,用于傳遞錯誤值

    將下面的setter與等價的Promise代碼比較,可以看出:

    • Promise只提供一次值,且不會在兩個console.log輸出

    • Promise的返回值是異步返回的:

    setter-setter的實現:

    function setSetTen(setTen) {
      setTen(10)
      setTen(10)
    }
    
    console.log('before setSetTen');
    setSetTen(console.log);
    console.log('after setSetTen');
    
    // (Log shows:)
    // before setSetTen
    // 10
    // 10
    // after setSetTen

    promise的實現:

    const tenPromise = new Promise(function setSetTen(setTen) {
      setTen(10);
      setTen(10);
    });
    
    console.log('before Promise.then');
    tenPromise.then(console.log);
    console.log('after Promise.then');
    
    // (Log shows:)
    // before Promise.then
    // after Promise.then
    // 10

    Promise可以方便的用于表示:一個異步且只返回一次的值。 在ES2017以后,可以使用async - await語法糖來編寫Promise。 在函數前使用async關鍵字,在需要使用Promise值的位置使用await來接收值。

    async function main() {
      console.log('before await');
      const ten = await new Promise(function setSetTen(setTen) {
        setTen(10);
      });
      console.log(ten);
      console.log('after await');
    }
    
    main();
    
    // (Log shows:)
    // before await
    // 10
    // after await

    語法糖async - await也可用于創建Promise, 因為async函數將返回一個Promise對象,該Promise對象將返回return的值。

    async function getTenPromise() {
      return 10;
    }
    const tenPromise = getTenPromise();
    
    console.log('before Promise.then');
    tenPromise.then(console.log);
    console.log('after Promise.then');
    
    // (Log shows:)
    // before Promise.then
    // after Promise.then
    // 10

    Observables

    observable是(省略了一些細節:)一個包含有3個setter的setter函數,并帶有額外的保障。
    函數定義: (X => (), Err => (), () => ()) => ()

    JavaScript?getter?setter金字塔???????怎么實現

    GetterSetterFunctionValue

    像Iterables一樣,GetterSetterFunctionValue是一種特殊類型的getter-getter,它增加了發送完成信號的能力,Observable也是一種setter-setter,它也增加了完成能力。
    JavaScript中的典型setter-setter,如: element.addEventListener不會通知事件流是否完成,因此很難連接事件流或執行其他與完成相關的邏輯。

    與JavaScript規范中標準化的可伸縮性不同,可觀測性是在幾個庫中找到的松散約定,如:

    • RxJS

    • most.js

    • xstream

    • Bacon.js

    盡管正在考慮將proposal-observable作為一個TC39方案,但該方案仍在不斷修改。
    因此在本文中,讓我們假設遵循Fantasy Observable規范(其中RxJS、most.js和xstream等最受歡迎庫都遵循這一規范)。

    Observables the dual of Iterables,有以下特性:

    可迭代:

    • 它是一個對象

    • 可迭代,有一個“iterate”屬性方法,即:Symbol.iterator

    • “iterate” 方法是迭代器對象的 getter 

    • 迭代器對象有一個名為next的 getter

    可觀察:

    • 它是一個對象

    • 有可觀察method,即:subscribe

    • 可觀察method是Observer對象的setter

    • Observer有一個名為nextsetter

    Observer對象還可以包含另外兩個方法:

    • complete,表示成功完成,相當于iterator中的“done”指示符

    • error,表示失敗完成,相當iterator中執行時引發異常

    與Promise一樣,Observable為返回值增加了一些保障:

    • 一旦調用了complete,則不會調用error

    • 一旦調用了error,就不會調用complete

    • 一旦調用了complete或error,則不會調用next

    在下面的示例中,Observable用于異步返回有限的數字序列

    const oddNums = {
      subscribe: (observer) => {
        let x = 40;
        let clock = setInterval(() => {
          if (x <= 48) {
            observer.next(x);
            x += 2;
          } else {
            observer.complete();
            clearInterval(clock);
          }
        }, 1000);
      }
    };
    
    oddNums.subscribe({
      next: x => console.log(x),
      complete: () => console.log('done'),
    });
    
    // (Log shows:)
    // 40
    // 42
    // 44
    // 46
    // 48
    // done

    與setter-setter一樣,Observable具有控制反轉的能力,因此消費端(oddNums.subscribe)無法暫停或取消傳入的數據流。
    大多數Observable的實現都添加了一個重要的細節,允許消費者取消訂閱: unsubscribe

    “subscribe”函數將返回一個對象subscription,即“unsubscribe”。 消費端可以使用該方法取消訂閱。
    因此,“subscribe”不再是setter,因為它是一個具有輸入(觀察者)和輸出(訂閱)的函數。

    下面,我們在前面的示例中添加了一個訂閱對象:

    const oddNums = {
      subscribe: (observer) => {
        let x = 40;
        let clock = setInterval(() => {
          if (x <= 48) {
            observer.next(x);
            x += 2;
          } else {
            observer.complete();
            clearInterval(clock);
          }
        }, 1000);
        // ???? Subscription:
        return {
          unsubscribe: () => {
            clearInterval(clock);
          }
        };
      }
    };
    
    const subscription = oddNums.subscribe({
      next: x => console.log(x),
      complete: () => console.log('done'),
    });
    
    // ???? Cancel the incoming flow of data after 2.5 seconds
    setTimeout(() => {
      subscription.unsubscribe();
    }, 2500);
    
    // (Log shows:)
    // 40
    // 42

    async iterables

    異步可迭代函數(省略了一些細節)類似于yield promise的可迭代函數
    函數定義: () => (() => Promise<{done, value}>)

    JavaScript?getter?setter金字塔???????怎么實現

    Iterables可以表示任何無限或有限的值序列,但它們有一個限制:

    • 只要使用者調用next()方法,返回值就必須是同步的。

    AsyncIterables擴展了Iterables的功能,它通過允許延后返回值,而不是在調用時立即返回。
    AsyncIterables通過使用Promise實現值的異步傳遞,因為Promise表示單個異步值。每次調用迭代器的next()(內部getter函數),都會創建并返回一個Promise。 在下面的示例中,我們以oddNums可迭代為例,其在迭代時每次返回一個Promise對象:

    function slowResolve(val) {
      return new Promise(resolve => {
        setTimeout(() => resolve(val), 1000);
      });
    }
    
    function* oddNums() {
      let i = 40;
      while (true) {
        if (i <= 48) {
          yield slowResolve(i); // ???? yield a Promise
          i += 2;
        } else {
          return;
        }
      }
    }

    要使用Asynciteable,我們可以使用async - await語法糖,來遍歷&獲取異步迭代器的值:

    async function main() {
      for (let promise of oddNums()) {
        const x = await promise;
        console.log(x);
      }
      console.log('done');
    }
    main();
    // (Log shows:)
    // 40
    // 42
    // 44
    // 46
    // 48
    // done

    雖然上例中通過async - await語法糖(ES6語法)能夠編寫出可讀性較好的代碼。但是,在ES2018中,異步迭代是通過{done,value}(Promise)對象來迭代的。

    比較一下ES6&ES2018異步迭代器的函數定義:

    • ES6異步迭代器: () => (() => {done, value: Promise<X>})

    • ES2018異步迭代器: () => (() => Promise<{done, value}>)

    可以看出,ES2018異步可迭代函數返回的不是一個可迭代函數,它將返回一個Promise對象,但在許多方面與ES6異步迭代器相似。
    這一細節的原因是,異步可伸縮性還需要允許異步發送完成(done),因此Promise必須包裹{done,value}對象。

    因為AsyncIterables不是Iterables,所以它們使用不同的符號。

    • Iterables 使用Symbol.iterator

    • AsyncIterables 使用'Symbol.asyncItrator'

    在下面的示例中,我們使用ES2018 AsyncIterable實現了一個前例等價的功能:

    const oddNums = {
      [Symbol.asyncIterator]: () => {
        let i = 40;
        return {
          next: () => {
            if (i <= 48) {
              const next = i;
              i += 2;
              return slowResolve({done: false, value: next});
            } else {
              return slowResolve({done: true});
            }
          }
        };
      }
    };
    
    async function main() {
      let iter = oddNums[Symbol.asyncIterator]();
      let done = false;
      for (let promise = iter.next(); !done; promise = iter.next()) {
        const result = await promise;
        done = result.done;
        if (!done) console.log(result.value);
      }
      console.log('done');
    }
    main();

    像Iterables有語法糖function*for&ndash;let&ndash;of,以及Promises有async&ndash;await語法糖一樣,ES2018中的AsyncIterable有兩個語法糖功能:

    • 生產端:async function*

    • 消費端:for&ndash;await&ndash;let&ndash;of

    在下面的示例中,我們使用這兩種功能創建異步數字序列,并使用for-await循環遍歷它們:

    function sleep(period) {
      return new Promise(resolve => {
        setTimeout(() => resolve(true), period);
      });
    }
    
    // ???? Production side can use both `await` and `yield`
    async function* oddNums() {
      let i = 40;
      while (true) {
        if (i <= 48) {
          await sleep(1000);
          yield i;
          i += 2;
        } else {
          await sleep(1000);
          return;
        }
      }
    }
    
    async function main() {
      // ???? Consumption side uses the new syntax `for await`
      for await (let x of oddNums()) {
        console.log(x);
      }
      console.log('done');
    }
    
    main();

    盡管它們是新特性,但Babel、TypeScript、Firefox、Chrome、Safari 和 Node.js中都已經支持了。

    AsyncIterables可以方便地結合基于Promise的API(如fetch)來創建異步序列。 例如在數據庫中列出用戶,每次請求一個用戶:

    async function* users(from, to) {
      for (let x = from; x <= to; x++) {
        const res = await fetch('http://jsonplaceholder.typicode.com/users/' + x);
        const json = await res.json();
        yield json;
      }
    }
    
    async function main() {
      for await (let x of users(1, 10)) {
        console.log(x);
      }
    }
    
    main();

    operators

    在本文中,抽象的列舉了一些特殊的JavaScript函數示例。 根據定義,它們的功能的不可能比函數更強大。因此,函數是最強大、最靈活的抽象。完全靈活性的缺點是不可預測性,這些抽象提供的是“保證”,基于這些“保證”,讓您可以編寫更有組件、更可預測的代碼。

    另一方向, 函數可以作為JavaScript的值,允許將它進行傳遞和操縱。
    在本文中,我們將Iterable、Observable、AsyncIterable作為值進行傳遞,并在傳遞過程中對其進行操作。

    最常見的操作之一是map映射,它在數組中經常使用到,但也與其他抽象相關。 在下面的示例中,我們為AsyncIterables創建map操作符,并使用它用來創建異步迭代器,以獲取數據庫的用戶信息。

    async function* users(from, to) {
      for (let i = from; i <= to; i++) {
        const res = await fetch('http://jsonplaceholder.typicode.com/users/' + i);
        const json = await res.json();
        yield json;
      }
    }
    
    // ???? Map operator for AsyncIterables
    async function* map(inputAsyncIter, f) {
      for await (let x of inputAsyncIter) {
        yield f(x);
      }
    }
    
    async function main() {
      const allUsers = users(1, 10);
      // ???? Pass `allUsers` around, create a new AsyncIterable `names`
      const names = map(allUsers, user => user.name);
      for await (let name of names) {
        console.log(name);
      }
    }
    
    main();

    上面的示例代碼,沒有被抽象至Getter - Setter金字塔中。
    若使用getter - setter來實現,需要更多的代碼,可讀性也不好。
    因此,在不犧牲可讀性的情況下,使用運算符和新的語法糖,用更少的代碼編寫函數做更多的事情,以處理這種特殊的場景。

    JavaScript?getter?setter金字塔???????怎么實現

    關于“JavaScript getter setter金字塔怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    章丘市| 开江县| 竹山县| 高雄县| 聂荣县| 岑溪市| 安乡县| 临朐县| 威海市| 蒲城县| 南陵县| 马边| 茌平县| 镇原县| 泸州市| 靖远县| 福建省| 西安市| 河曲县| 罗山县| 孟州市| 横峰县| 双峰县| 五华县| 茶陵县| 光山县| 宝丰县| 荣成市| 嫩江县| 灵丘县| 中西区| 广东省| 宿松县| 灵石县| 台东市| 泸定县| 霍山县| 广西| 邛崃市| 莆田市| 庆城县|