主頁 > 前端設計 > ES6 (二十九)ES6最新提案、do、throw、函式部分執行、管道運算子|>、柯里化、::、Realm API

ES6 (二十九)ES6最新提案、do、throw、函式部分執行、管道運算子|>、柯里化、::、Realm API

2021-08-15 07:53:45 前端設計

ES6 (二十九)ES6最新提案、do、throw、函式部分執行、管道運算子|>、柯里化、::、Realm API

文章目錄

  • ES6 (二十九)ES6最新提案、do、throw、函式部分執行、管道運算子|>、柯里化、::、Realm API
    • 1. do 運算式
    • 2. throw 運算式
    • 3. 函式的部分執行
      • 語法
      • 注意點
    • 4. 管道運算子
    • 5. Math.signbit()
    • 6. 雙冒號運算子
    • 7. Realm API
    • 8. `#!`命令
    • 9. import.meta
    • 10. JSON 模塊

1. do 運算式

本質上,塊級作用域是一個陳述句,將多個操作封裝在一起,沒有回傳值,

{
  let t = f();
  t = t * t + 1;
}

上面代碼中,塊級作用域將兩個陳述句封裝在一起,但是,在塊級作用域以外,沒有辦法得到t的值,因為塊級作用域不回傳值,除非t是全域變數,

現在有一個提案,使得塊級作用域可以變為運算式,也就是說可以回傳值,辦法就是在塊級作用域之前加上do,使它變為do運算式,然后就會回傳內部最后執行的運算式的值,

let x = do {
  let t = f();
  t * t + 1;
};

上面代碼中,變數x會得到整個塊級作用域的回傳值(t * t + 1),

do運算式的邏輯非常簡單:封裝的是什么,就會回傳什么,

// 等同于 <運算式>
do { <運算式>; }

// 等同于 <陳述句>
do { <陳述句> }

do運算式的好處是可以封裝多個陳述句,讓程式更加模塊化,就像樂高積木那樣一塊塊拼裝起來,

let x = do {
  if (foo()) { f() }
  else if (bar()) { g() }
  else { h() }
};

上面代碼的本質,就是根據函式foo的執行結果,呼叫不同的函式,將回傳結果賦給變數x,使用do運算式,就將這個操作的意圖表達得非常簡潔清晰,而且,do塊級作用域提供了單獨的作用域,內部操作可以與全域作用域隔絕,

值得一提的是,do運算式在 JSX 語法中非常好用,

return (
  <nav>
    <Home />
    {
      do {
        if (loggedIn) {
          <LogoutButton />
        } else {
          <LoginButton />
        }
      }
    }
  </nav>
)

上面代碼中,如果不用do運算式,就只能用三元判斷運算子(?:),那樣的話,一旦判斷邏輯復雜,代碼就會變得很不易讀,

2. throw 運算式

JavaScript 語法規定throw是一個命令,用來拋出錯誤,不能用于運算式之中,

// 報錯
console.log(throw new Error());

上面代碼中,console.log的引數必須是一個運算式,如果是一個throw陳述句就會報錯,

現在有一個提案,允許throw用于運算式,

// 引數的默認值
function save(filename = throw new TypeError("Argument required")) {
}

// 箭頭函式的回傳值
lint(ast, {
  with: () => throw new Error("avoid using 'with' statements.")
});

// 條件運算式
function getEncoder(encoding) {
  const encoder = encoding === "utf8" ?
    new UTF8Encoder() :
    encoding === "utf16le" ?
      new UTF16Encoder(false) :
      encoding === "utf16be" ?
        new UTF16Encoder(true) :
        throw new Error("Unsupported encoding");
}

// 邏輯運算式
class Product {
  get id() {
    return this._id;
  }
  set id(value) {
    this._id = value || throw new Error("Invalid value");
  }
}

上面代碼中,throw都出現在運算式里面,

語法上,throw運算式里面的throw不再是一個命令,而是一個運算子,為了避免與throw命令混淆,規定throw出現在行首,一律解釋為throw陳述句,而不是throw運算式,

3. 函式的部分執行

語法

多引數的函式有時需要系結其中的一個或多個引數,然后回傳一個新函式,

function add(x, y) { return x + y; }
function add7(x) { return x + 7; }

上面代碼中,add7函式其實是add函式的一個特殊版本,通過將一個引數系結為7,就可以從add得到add7

// bind 方法
const add7 = add.bind(null, 7);

// 箭頭函式
const add7 = x => add(x, 7);

上面兩種寫法都有些冗余,其中,bind方法的局限更加明顯,它必須提供this,并且只能從前到后一個個系結引數,無法只系結非頭部的引數,

現在有一個提案,使得系結引數并回傳一個新函式更加容易,這叫做函式的部分執行(partial application),

const add = (x, y) => x + y;
const addOne = add(1, ?);//`?`和`...`只能出現在函式的呼叫之中,并且會回傳一個新函式,

const maxGreaterThanZero = Math.max(0, ...);

根據新提案,?是單個引數的占位符,...是多個引數的占位符,以下的形式都屬于函式的部分執行,

f(x, ?)
f(x, ...)
f(?, x)
f(..., x)
f(?, x, ?)
f(..., x, ...)

?...只能出現在函式的呼叫之中,并且會回傳一個新函式,

const g = f(?, 1, ...);
// 等同于
const g = (x, ...y) => f(x, 1, ...y);

函式的部分執行,也可以用于物件的方法,

let obj = {
  f(x, y) { return x + y; },
};

const g = obj.f(?, 3);
g(1) // 4

注意點

函式的部分執行有一些特別注意的地方,

(1)函式的部分執行是基于原函式的,如果原函式發生變化,部分執行生成的新函式也會立即反映這種變化,

let f = (x, y) => x + y;

const g = f(?, 3);
g(1); // 4

// 替換函式 f
f = (x, y) => x * y;

g(1); // 3

上面代碼中,定義了函式的部分執行以后,更換原函式會立即影響到新函式,

(2)如果預先提供的那個值是一個運算式,那么這個運算式并不會在定義時求值,而是在每次呼叫時求值,

let a = 3;
const f = (x, y) => x + y;

const g = f(?, a);
g(1); // 4

// 改變 a 的值
a = 10;
g(1); // 11 每次呼叫函式`g`的時候,才會對`a`進行求值,

上面代碼中,預先提供的引數是變數a,那么每次呼叫函式g的時候,才會對a進行求值,

(3)如果新函式的引數多于占位符的數量,那么多余的引數將被忽略,

const f = (x, ...y) => [x, ...y];
const g = f(?, 1);
g(2, 3, 4); // [2, 1]

上面代碼中,函式g只有一個占位符,也就意味著它只能接受一個引數,多余的引數都會被忽略,

寫成下面這樣,多余的引數就沒有問題,

const f = (x, ...y) => [x, ...y];
const g = f(?, 1, ...);
g(2, 3, 4); // [2, 1, 3, 4];

(4)...只會被采集一次,如果函式的部分執行使用了多個...,那么每個...的值都將相同,

const f = (...x) => x;
const g = f(..., 9, ...);
g(1, 2, 3); // [1, 2, 3, 9, 1, 2, 3]

上面代碼中,g定義了兩個...占位符,真正執行的時候,它們的值是一樣的,

4. 管道運算子

Unix 作業系統有一個管道機制(pipeline),可以把前一個操作的值傳給后一個操作,這個機制非常有用,使得簡單的操作可以組合成為復雜的操作,許多語言都有管道的實作,現在有一個提案,讓 JavaScript 也擁有管道機制,

JavaScript 的管道是一個運算子,寫作|>,它的左邊是一個運算式,右邊是一個函式,管道運算子把左邊運算式的值,傳入右邊的函式進行求值,

x |> f
// 等同于
f(x)

管道運算子最大的好處,就是可以把嵌套的函式,寫成從左到右的鏈式運算式,

function doubleSay (str) {
  return str + ", " + str;
}

function capitalize (str) {
  return str[0].toUpperCase() + str.substring(1);
}

function exclaim (str) {
  return str + '!';
}

上面是三個簡單的函式,如果要嵌套執行,傳統的寫法和管道的寫法分別如下,

// 傳統的寫法
exclaim(capitalize(doubleSay('hello')))
// "Hello, hello!"

// 管道的寫法
'hello'
  |> doubleSay
  |> capitalize
  |> exclaim
// "Hello, hello!"

管道運算子只能傳遞一個值,這意味著它右邊的函式必須是一個單引數函式,如果是多引數函式,就必須進行柯里化,改成單引數的版本,

柯里化(回傳新函式):

  • 柯里化,英語:Currying(果然是滿滿的英譯中的既視感),是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,并且回傳接受余下的引數而且回傳結果的新函式的技術,
  • 看這個解釋有一點抽象,我們就拿被做了無數次示例的add函式,來做一個簡單的實作,
// 普通的add函式
function add(x, y) {
    return x + y
}

// Currying后
function curryingAdd(x) {
    return function (y) {
        return x + y
    }
}

add(1, 2)           // 3
curryingAdd(1)(2)   // 3
  • 實際上就是把add函式的x,y兩個引數變成了先用一個函式接收x然后回傳一個函式去處理y引數,現在思路應該就比較清晰了,就是只傳遞給函式一部分引數來呼叫它,讓它回傳一個函式去處理剩下的引數,
  • Currying有哪些好處呢:
    • 引數復用
    • 提前確認
    • 延遲運行:像我們js中經常使用的bind,實作的機制就是Currying.
function double (x) { return x + x; }
function add (x, y) { return x + y; }

let person = { score: 25 };
person.score
  |> double
  |> (_ => add(7, _))
// 57

上面代碼中,add函式需要兩個引數,但是,管道運算子只能傳入一個值,因此需要事先提供另一個引數,并將其改成單引數的箭頭函式_ => add(7, _),這個函式里面的下劃線并沒有特別的含義,可以用其他符號代替,使用下劃線只是因為,它能夠形象地表示這里是占位符,

管道運算子對于await函式也適用,

x |> await f
// 等同于
await f(x)

const userAge = userId |> await fetchUserById |> getAgeFromUser;
// 等同于
const userAge = getAgeFromUser(await fetchUserById(userId));

5. Math.signbit()

Math.sign()用來判斷一個值的正負,但是如果引數是-0,它會回傳-0

Math.sign(-0) // -0

這導致對于判斷符號位的正負,Math.sign()不是很有用,JavaScript 內部使用 64 位浮點數(國際標準 IEEE 754)表示數值,IEEE 754 規定第一位是符號位,0表示正數,1表示負數,所以會有兩種零,+0是符號位為0時的零值,-0是符號位為1時的零值,實際編程中,判斷一個值是+0還是-0非常麻煩,因為它們是相等的,

+0 === -0 // true

目前,有一個提案,引入了Math.signbit()方法判斷一個數的符號位是否設定了,

Math.signbit(2) //false
Math.signbit(-2) //true
Math.signbit(0) //false
Math.signbit(-0) //true

可以看到,該方法正確回傳了-0的符號位是設定了的,

該方法的演算法如下,

  • 如果引數是NaN,回傳false
  • 如果引數是-0,回傳true
  • 如果引數是負值,回傳true
  • 其他情況回傳false

6. 雙冒號運算子

箭頭函式可以系結this物件,大大減少了顯式系結this物件的寫法(callapplybind),但是,箭頭函式并不適用于所有場合,所以現在有一個提案,提出了“函式系結”(function bind)運算子,用來取代callapplybind呼叫,

函式系結運算子是并排的兩個冒號(::),雙冒號左邊是一個物件,右邊是一個函式,該運算子會自動將左邊的物件,作為背景關系環境(即this物件),系結到右邊的函式上面,

foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
  return obj::hasOwnProperty(key);
}

如果雙冒號左邊為空,右邊是一個物件的方法,則等于將該方法系結在該物件上面,

var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;

let log = ::console.log;
// 等同于
var log = console.log.bind(console);

如果雙冒號運算子的運算結果,還是一個物件,就可以采用鏈式寫法,

import { map, takeWhile, forEach } from "iterlib";

getPlayers()
::map(x => x.character())
::takeWhile(x => x.strength > 100)
::forEach(x => console.log(x));

7. Realm API

Realm API 提供沙箱功能(sandbox),允許隔離代碼,防止那些被隔離的代碼拿到全域物件,

以前,經常使用<iframe>作為沙箱,

const globalOne = window;
let iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const globalTwo = iframe.contentWindow;

上面代碼中,<iframe>的全域物件是獨立的(iframe.contentWindow),Realm API 可以取代這個功能,

const globalOne = window;
const globalTwo = new Realm().global;

上面代碼中,Realm API單獨提供了一個全域物件new Realm().global

Realm API 提供一個Realm()建構式,用來生成一個 Realm 物件,該物件的global屬性指向一個新的頂層物件,這個頂層物件跟原始的頂層物件類似,

const globalOne = window;
const globalTwo = new Realm().global;

globalOne.evaluate('1 + 2') // 3
globalTwo.evaluate('1 + 2') // 3

上面代碼中,Realm 生成的頂層物件的evaluate()方法,可以運行代碼,

下面的代碼可以證明,Realm 頂層物件與原始頂層物件是兩個物件,

let a1 = globalOne.evaluate('[1,2,3]');
let a2 = globalTwo.evaluate('[1,2,3]');
a1.prototype === a2.prototype; // false
a1 instanceof globalTwo.Array; // false
a2 instanceof globalOne.Array; // false

上面代碼中,Realm 沙箱里面的陣列的原型物件,跟原始環境里面的陣列是不一樣的,

Realm 沙箱里面只能運行 ECMAScript 語法提供的 API,不能運行宿主環境提供的 API,

globalTwo.evaluate('console.log(1)')
// throw an error: console is undefined

上面代碼中,Realm 沙箱里面沒有console物件,導致報錯,因為console不是語法標準,是宿主環境提供的,

如果要解決這個問題,可以使用下面的代碼,

globalTwo.console = globalOne.console;

Realm()建構式可以接受一個引數物件,該引數物件的intrinsics屬性可以指定 Realm 沙箱繼承原始頂層物件的方法,

const r1 = new Realm();
r1.global === this;
r1.global.JSON === JSON; // false

const r2 = new Realm({ intrinsics: 'inherit' });
r2.global === this; // false
r2.global.JSON === JSON; // true

上面代碼中,正常情況下,沙箱的JSON方法不同于原始的JSON物件,但是,Realm()建構式接受{ intrinsics: 'inherit' }作為引數以后,就會繼承原始頂層物件的方法,

用戶可以自己定義Realm的子類,用來定制自己的沙箱,

class FakeWindow extends Realm {
  init() {
    super.init();
    let global = this.global;

    global.document = new FakeDocument(...);
    global.alert = new Proxy(fakeAlert, { ... });
    // ...
  }
}

上面代碼中,FakeWindow模擬了一個假的頂層物件window

8. #!命令

Unix 的命令列腳本都支持#!命令,又稱為 Shebang 或 Hashbang,這個命令放在腳本的第一行,用來指定腳本的執行器,

比如 Bash 腳本的第一行,

#!/bin/sh

Python 腳本的第一行,

#!/usr/bin/env python

現在有一個提案,為 JavaScript 腳本引入了#!命令,寫在腳本檔案或者模塊檔案的第一行,

// 寫在腳本檔案第一行
#!/usr/bin/env node
'use strict';
console.log(1);

// 寫在模塊檔案第一行
#!/usr/bin/env node
export {};
console.log(1);

有了這一行以后,Unix 命令列就可以直接執行腳本,

# 以前執行腳本的方式
$ node hello.js

# hashbang 的方式
$ ./hello.js

對于 JavaScript 引擎來說,會把#!理解成注釋,忽略掉這一行,

9. import.meta

開發者使用一個模塊時,有時需要知道模板本身的一些資訊(比如模塊的路徑),現在有一個提案,為 import 命令添加了一個元屬性import.meta,回傳當前模塊的元資訊,

import.meta只能在模塊內部使用,如果在模塊外部使用會報錯,

這個屬性回傳一個物件,該物件的各種屬性就是當前運行的腳本的元資訊,具體包含哪些屬性,標準沒有規定,由各個運行環境自行決定,一般來說,import.meta至少會有下面兩個屬性,

(1)import.meta.url

import.meta.url回傳當前模塊的 URL 路徑,舉例來說,當前模塊主檔案的路徑是https://foo.com/main.jsimport.meta.url就回傳這個路徑,如果模塊里面還有一個資料檔案data.txt,那么就可以用下面的代碼,獲取這個資料檔案的路徑,

new URL('data.txt', import.meta.url)

注意,Node.js 環境中,import.meta.url回傳的總是本地路徑,即是file:URL協議的字串,比如file:///home/user/foo.js

(2)import.meta.scriptElement

import.meta.scriptElement是瀏覽器特有的元屬性,回傳加載模塊的那個<script>元素,相當于document.currentScript屬性,

// HTML 代碼為
// <script type="module" src="my-module.js" data-foo="abc"></script>

// my-module.js 內部執行下面的代碼
import.meta.scriptElement.dataset.foo
// "abc"

10. JSON 模塊

import 命令目前只能用于加載 ES 模塊,現在有一個提案,允許加載 JSON 模塊,

假定有一個 JSON 模塊檔案config.json

{
  "appName": "My App"
}

目前,只能使用fetch()加載 JSON 模塊,

const response = await fetch('./config.json');
const json = await response.json();

import 命令能夠直接加載 JSON 模塊以后,就可以像下面這樣寫,

import configData from './config.json' assert { type: "json" };
console.log(configData.appName);

上面示例中,整個 JSON 物件被匯入為configData物件,然后就可以從該物件獲取 JSON 資料,

==import命令匯入 JSON 模塊時,命令結尾的assert {type: "json"}不可缺少,這叫做匯入斷言,用來告訴 JavaScript 引擎,現在加載的是 JSON 模塊,==你可能會問,為什么不通過.json后綴名判斷呢?因為瀏覽器的傳統是不通過后綴名判斷檔案型別,標準委員會希望遵循這種做法,這樣也可以避免一些安全問題,

匯入斷言是 JavaScript 匯入其他格式模塊的標準寫法,JSON 模塊將是第一個使用這種語法匯入的模塊,以后,還會支持匯入 CSS 模塊、HTML 模塊等等,

動態加載模塊的import()函式也支持加載 JSON 模塊,

import('./config.json', { assert: { type: 'json' } })

腳本加載 JSON 模塊以后,還可以再用 export 命令輸出,這時,可以將 export 和 import 結合成一個陳述句,

export { config } from './config.json' assert { type: 'json' };

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/293749.html

標籤:其他

上一篇:javascript高級(二)

下一篇:Java專案:醫院預約掛號系統(java+Springboot+jsp+maven+layui+mysql)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • vue移動端上拉加載

    可能做得過于簡單或者比較low,請各位大佬留情,一起探討技術 ......

    uj5u.com 2020-09-10 04:38:07 more
  • 優美網站首頁,頂部多層導航

    一個個人用的瀏覽器首頁,可以把一下常用的網站放在這里,平常打開會比較方便。 第一步,HTML代碼 <script src=https://www.cnblogs.com/szharf/p/"js/jquery-3.4.1.min.js"></script> <div id="navigate"> <ul> <li class="labels labels_1"> ......

    uj5u.com 2020-09-10 04:38:47 more
  • 頁面為要加<!DOCTYPE html>

    最近因為寫一個js函式,需要用到$(window).height(); 由于手寫demo的時候,過于自信,其實對前端方面的認識也不夠體系,用文本檔案直接敲出來的html代碼,第一行沒有加上<!DOCTYPE html> 導致了$(window).height();的結果直接是整個document的高 ......

    uj5u.com 2020-09-10 04:38:52 more
  • WordPress網站程式手動升級要做好資料備份

    WordPress博客網站程式在進行升級前,必須要做好網站資料的備份,這個問題良家佐言是遇見過的;在剛開始接觸WordPress博客程式的時候,因為升級問題和博客網站的修改的一些嘗試,良家佐言是吃盡了苦頭。因為購買的是西部數碼的空間和域名,每當佐言把自己的WordPress博客網站搞到一塌糊涂的時候 ......

    uj5u.com 2020-09-10 04:39:30 more
  • WordPress程式不能升級為5.4.2版本的原因

    WordPress是一款個人博客系統,受到英文博客愛好者和中文博客愛好者的追捧,并逐步演化成一款內容管理系統軟體;它是使用PHP語言和MySQL資料庫開發的,用戶可以在支持PHP和MySQL資料庫的服務器上使用自己的博客。每一次WordPress程式的更新,就會牽動無數WordPress愛好者的心, ......

    uj5u.com 2020-09-10 04:39:49 more
  • 使用CSS3的偽元素進行首字母下沉和首行改變樣式

    網頁中常見的一種效果,首字改變樣式或者首行改變樣式,效果如下圖。 代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ......

    uj5u.com 2020-09-10 04:40:09 more
  • 關于a標簽的講解

    什么是a標簽? <a> 標簽定義超鏈接,用于從一個頁面鏈接到另一個頁面。 <a> 元素最重要的屬性是 href 屬性,它指定鏈接的目標。 a標簽的語法格式:<a href=https://www.cnblogs.com/summerxbc/p/"指定要跳轉的目標界面的鏈接">需要展示給用戶看見的內容</a> a標簽 在所有瀏覽器中,鏈接的默認外觀如下: 未被訪問的鏈接帶 ......

    uj5u.com 2020-09-10 04:40:11 more
  • 前端輪播圖

    在需要輪播的頁面是引入swiper.min.js和swiper.min.css swiper.min.js地址: 鏈接:https://pan.baidu.com/s/15Uh516YHa4CV3X-RyjEIWw 提取碼:4aks swiper.min.css地址 鏈接:https://pan.b ......

    uj5u.com 2020-09-10 04:40:13 more
  • 如何設定html中的背景圖片(全屏顯示,且不拉伸)

    1 <style>2 body{background-image:url(https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture); 3 background-size:cover;background ......

    uj5u.com 2020-09-10 04:40:16 more
  • Java學習——HTML詳解(上)

    HTML詳解 初識HTML Hyper Text Markup Language(超文本標記語言) 1 <!--DOCTYPE:告訴瀏覽器我們要使用什么規范--> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <!--meta 描述性的標簽,描述一些 ......

    uj5u.com 2020-09-10 04:40:33 more
最新发布
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 07:59:23 more
  • 生產事故-走近科學之消失的JWT

    入職多年,面對生產環境,盡管都是小心翼翼,慎之又慎,還是難免捅出簍子。輕則滿頭大汗,面紅耳赤。重則系統停擺,損失資金。每一個生產事故的背后,都是寶貴的經驗和教訓,都是專案成員的血淚史。為了更好地防范和遏制今后的各類事故,特開此專題,長期更新和記錄大大小小的各類事故。有些是親身經歷,有些是經人耳傳口授 ......

    uj5u.com 2023-04-18 07:55:04 more
  • 記錄--Canvas實作打飛字游戲

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 打開游戲界面,看到一個畫面簡潔、卻又富有挑戰性的游戲。螢屏上,有一個白色的矩形框,里面不斷下落著各種單詞,而我需要迅速地輸入這些單詞。如果我輸入的單詞與螢屏上的單詞匹配,那么我就可以獲得得分;如果我輸入的單詞錯誤或者時間過長,那么我就會輸 ......

    uj5u.com 2023-04-04 08:35:30 more
  • 了解 HTTP 看這一篇就夠

    在學習網路之前,了解它的歷史能夠幫助我們明白為何它會發展為如今這個樣子,引發探究網路的興趣。下面的這張圖片就展示了“互聯網”誕生至今的發展歷程。 ......

    uj5u.com 2023-03-16 11:00:15 more
  • 藍牙-低功耗中心設備

    //11.開啟藍牙配接器 openBluetoothAdapter //21.開始搜索藍牙設備 startBluetoothDevicesDiscovery //31.開啟監聽搜索藍牙設備 onBluetoothDeviceFound //30.停止監聽搜索藍牙設備 offBluetoothDevi ......

    uj5u.com 2023-03-15 09:06:45 more
  • canvas畫板(滑鼠和觸摸)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canves</title> <style> #canvas { cursor:url(../images/pen.png),crosshair; } #canvasdiv{ bo ......

    uj5u.com 2023-02-15 08:56:31 more
  • 手機端H5 實作自定義拍照界面

    手機端 H5 實作自定義拍照界面也可以使用 MediaDevices API 和 <video> 標簽來實作,和在桌面端做法基本一致。 首先,使用 MediaDevices.getUserMedia() 方法獲取攝像頭媒體流,并將其傳遞給 <video> 標簽進行渲染。 接著,使用 HTML 的 < ......

    uj5u.com 2023-01-12 07:58:22 more
  • 記錄--短視頻滑動播放在 H5 下的實作

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 短視頻已經無數不在了,但是主體還是使用 app 來承載的。本文講述 H5 如何實作 app 的視頻滑動體驗。 無聲勝有聲,一圖頂百辯,且看下圖: 網址鏈接(需在微信或者手Q中瀏覽) 從上圖可以看到,我們主要實作的功能也是本文要講解的有: ......

    uj5u.com 2023-01-04 07:29:05 more
  • 一文讀懂 HTTP/1 HTTP/2 HTTP/3

    從 1989 年萬維網(www)誕生,HTTP(HyperText Transfer Protocol)經歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發明。1996 年出現了 HTTP1.0。2015 年 HTTP2 正式發布。2020 年 HTTP3 或能正... ......

    uj5u.com 2022-12-24 06:56:02 more
  • 【HTML基礎篇002】HTML之form表單超詳解

    ??一、form表單是什么

    ??二、form表單的屬性

    ??三、input中的各種Type屬性值

    ??四、標簽 ......

    uj5u.com 2022-12-18 07:17:06 more