前端入門10-JavaScript語法之對象

来源:https://www.cnblogs.com/dasusu/archive/2018/12/03/10056824.html
-Advertisement-
Play Games

聲明 本系列文章內容全部梳理自以下幾個來源: 《JavaScript權威指南》 "MDN web docs" "Github:smyhvae/web" "Github:goddyZhao/Translation/JavaScript" 作為一個前端小白,入門跟著這幾個來源學習,感謝作者的分享,在其基 ...


聲明

本系列文章內容全部梳理自以下幾個來源:

作為一個前端小白,入門跟著這幾個來源學習,感謝作者的分享,在其基礎上,通過自己的理解,梳理出的知識點,或許有遺漏,或許有些理解是錯誤的,如有發現,歡迎指點下。

PS:梳理的內容以《JavaScript權威指南》這本書中的內容為主,因此接下去跟 JavaScript 語法相關的系列文章基本只介紹 ES5 標準規範的內容、ES6 等這系列梳理完再單獨來講講。

正文-對象

在 JavaScript 除了原始數據類型外,其餘均是對象,函數是對象,數組也是對象;繼承通過對象來實現,構造函數也通過對象來實現,所以對象在 JavaScript 里有著很重要的角色,理解和掌握對象的一些特性,對於掌握 JavaScript 這門語言有著很大的幫助。

Java 里對象有屬性和方法之分,但在 JavaScript 中,只存在屬性,變數是屬性,方法也是屬性,對於 JavaScript 來說,對象,其實只是一堆屬性的無序集合而已,外部可通過對象來操作各種屬性,只不過有的屬性,它的值是函數類型,所以這時可叫它為對象的方法。

對象的每個屬性,都是一個 key-value 的形式,屬性名和屬性值。而屬性,又分自有屬性和繼承屬性,自有屬性是指對象本身自己擁有的屬性,而繼承屬性是指繼承的屬性。

對象分類

一般來說,有三類對象,分別是內置對象、宿主對象、自定義對象:

  • 內置對象:是指語法標準規範中內置實現的一些對象,例如函數、數組、正則、日期等這些內置對象;
  • 宿主對象:是指 JavaScript 解釋器所嵌入的宿主環境,在前端里,一般來說宿主環境就是瀏覽器,瀏覽器也會定義一些內置對象,比如 HTMLElement 等;
  • 自定義對象:開發人員自行實現的對象。

創建對象

創建對象有三種方式:對象直接量、構造函數、Object.create()

對象直接量

這是最簡單的一種創建對象的方式,在代碼中,直接通過 {} 形式創建一個對象,如:

var book = {
    "main title": "JavaScript",
    'sub-title': "The Definitive Guide",
    "pages": 900,
    author: {
        firstname: "David",
        surname: "Flanagan"
    }
};

上述代碼中,等號右側 {} 代碼塊形式定義的對象方式,就叫對象直接量。代碼中,每出現一次對象直接量,會直接創建一個新的對象,對象的屬性就是對象直接量中定義的。

定義屬性時,有幾點需要註意一下,屬性名也就是 key 值,可加引號也可不加引號,但如果屬性名使用到一些保留字時,就肯定需要加引號。

屬性值可以是 JavaScript 中的任意類型,原始類型、對象類型都可以。

構造函數

構造函數就是通過 new 關鍵字和函數一起使用時,此時的函數就稱構造函數,用途在於創建一個新的對象。具體在後續講函數時會詳細講解。

這裡可以看個例子:

var o = new Object();
var o1 = new Object;
var a = new Array();

function Book() {}
var b = new Book();

通過 new 關鍵字和函數一起使用時,就可以創建新對象,例子中的 Object 和 Array 是內置的構造函數,也可以自定義構造函數,其實就是自定義一個函數,讓它和 new 關鍵字一起使用就可以了。

通過構造函數方式如何給新創建的對象添加一些初始化的屬性,這些細節和原理在函數一節中再講,這裡需要註意一點的就是,當不往構造函數傳參數時,此時括弧是允許可以省略的。

另外,第一種對象直接量的方式創建對象,其實,本質上也是通過構造函數:

var o = {name:"dasu"} 
//等效於
var o = new Object();
o.name = "dasu";

對象直接量其實是一種語法糖,可以通俗的理解,JavaScript 為方便我們創建對象,封裝的一層工具,其內部的本質實現也是通過構造函數。

Object.create()

你可以把 Object.create() 理解成 Java 中的靜態方法。

通過這種方式,可以創建一個新的對象,參數是指定對象要繼承的目標對象,這個被繼承的對象,在 JavaScript 里被稱為原型。

舉個例子:

var o = Object.create(new Object());  //創建一個新對象,讓它繼承自一個空對象

通過構造函數創建的對象,其繼承關係是由構造函數決定的,而 Object.create() 方式,可自己手動指定繼承關係。當然,並不是說,構造函數就無法自己指定繼承關係。

原型

原型可以理解成 Java 中的父類概念。

在 JavaScript 中,對象也存在繼承關係,繼承的雙方都是對象,對象是從對象上繼承的,被繼承的那個對象稱作原型。所以,有一種描述說,JavaScript 是基於原型的繼承。

在 Java 中,是通過 extends 關鍵字實現繼承關係,那麼在 JavaScript 里呢?

自然也有類似的用來指定對象的繼承關係,這就取決於創建對象的方式,上面說過,創建對象有三種方式:對象直接量、構造函數、Object.create(),但由於對象直接量本質上也是通過構造函數,所以其實就兩種。

對於構造函數創建的對象來說,因為每個函數都有一個 prototype 屬性,prototype 是它的屬性名,屬性值是一個對象,這個對象就是原型,就是通過該構造函數創建出來的新對象的繼承來源。

我們可以通過修改構造函數的 prototype 屬性值來達到指定對象繼承關係的目的,如果不修改,那麼內置的構造函數如 Object 或 Array 這些都已經有預設指定的 prototype 屬性值了,也就是創建內置對象時,這個對象已經具有一定的預設繼承結構了。

對於 Object.create() 方式創建對象,參數傳入的就是子對象的原型,想讓創建出來的對象繼承自哪裡,就傳入那個對象就可以了。這個方法必須傳入一個參數,否則運行時會拋異常,但可以傳入 null,表示不繼承任何對象,所以,JavaScript 里,是允許對象沒有原型,允許對象不具有繼承結構的。

對於原型,在後續會專門有一篇來講講,這裡大概清楚些概念即可。

添加屬性

JavaScript 里的對象,其實可以通俗的理解成屬性的集合,既然是作為容器的存在,那麼其實創建完對象只是第一步,後續就是往這個集合中添加屬性,所以 JavaScript 里,對象是允許在運行期間動態添加屬性的。

添加屬性的方式,可以通過對象直接量方式,在創建對象之時,就寫在對象直接量中,或者運行期間動態添加,如:

var o = {name:"dasu"}
o.age = 24;
o.sex = "man";
o.love = "girl";

添加屬性

但需要註意一點的是,不像 Java 中在編寫類代碼,為類添加成員變數時,可以只聲明卻初始化。在 JavaScript 中,是不允許這樣的。

也就是說,為對象添加某個屬性時,需要直接將屬性名和屬性值都設置好,其實想想也能明白,對象無非就是屬性的集合,你見過對哪個集合進行添加數據時,是可以只對該集合設置一個 key 值的嗎?

查詢屬性

訪問對象的屬性方式很簡單,兩種:. 運算符或 [] 運算符;

兩種方式都可以訪問對象的屬性,但有一個區別:

  • . 運算符訪問屬性的話,後面跟著的是屬性名
  • [] 運算符訪問屬性的話,中括弧內跟著的是屬性名的字元串

仍舊以上面例子中的代碼為例:

查詢屬性

由於通過 [] 運算符訪問對象的屬性,需要的是一個屬性名的字元串形式,所以這種方式會特別靈活,你可以再 [] 內放一個表達式也可以,只要表達式最後的結果是字元串,或者說可以自動類型轉換為屬性名的字元串即可,特別靈活。

. 運算符可能會比較習慣,但它就只能明明確確的通過屬性名來訪問了,如果你想通過某種拼接規則來生成屬性名,就只能用 [] 不能使用 .

如果訪問對象中某個不存在的屬性時,並不會拋異常,會輸出 undefined,但如果繼續訪問不存在的屬性的屬性時,等價於訪問 undefined 原始類型值的屬性,這就會拋異常了:

查詢不存在的屬性

ps:是不是發現,對對象的操作很像 Java 中對集合的操作?所以,有人解釋說對象是屬性的集合,這不是沒根據的。

刪除屬性

delete 是用來刪除對象上的屬性的,但它只是將該屬性名從對象上移除,並不刪除屬性值,舉個例子:

var a = [1,2,3];
var o = {name:"dasu", arr:a};

delete o.arr;
console.log(a[0]);  //輸出 => 1
console.log(o.arr); //輸出 => undefined

新鍵一個對象 o,它有個屬性 aar 存儲著數組 a,當通過 delete 刪除對象 o 上的 aar 屬性後,再去訪問這個 aar 屬性,獲取的是 undefined,表明這個屬性確實被刪除了,但本質上只是將其與這個對象 o 的關聯刪除掉,並不會刪除屬性值,所以輸出數組 a 的值時還是可以訪問到的。

不過,delete 有一些局限,它並不是什麼屬性都可以刪除:

  • 只能刪除自由屬性,無法刪除繼承屬性
  • 不能刪除那些可配置性為 false 的屬性

屬性擁有一些特性,在下麵會講,其中有一個是可配置性,當將這個特性設置為 false 時,就無法通過 delete 來刪除。

而之前說過的,通過 var 聲明的全局變數,雖然它最後是作為全局對象的屬性存在,但它的可配置性被設為 false,所以這些全局變數才無法通過 delete 被刪除。

嘗試刪除那些無法刪除的屬性,並不會讓程式出問題,delete 表達式有一個返回值,true 表示刪除成功,false 表示刪除失敗,僅此而已,沒有其他什麼副作用。

檢測屬性

因為 JavaScript 中對象的屬性太過動態性了,在運行期間,都無法確定某個屬性到底存不存在,某個到底是不是指定對象的屬性,所以這種場景,一般都需要進行屬性的檢測。

也就是檢測對象內是否含有某個屬性,有多種方式,下麵分別來介紹:

查詢屬性的方式

之前說過,訪問對象內不存在的屬性時,會返回 undefined,可以利用這點來判斷對象是否含有要訪問的屬性。

這種方式有個缺點,如果屬性值剛好被人為的手動設置成 undefined 時,就無法區別對象究竟有沒有這個屬性。

in 運算符方式

in 運算符左側是屬性名的字元串格式,右側是對象,當右側對象含有左側字元串同名的屬性時,返回 true,用這種方式就可以很好的判斷對象是否含有某個屬性。

檢測屬性

註意,左側必須是屬性名的字元串格式,跟 [] 運算符訪問對象屬性一樣的限制要求。

但這種方式有個局限,就是無法區分這個屬性究竟是自有屬性還是繼承屬性,也就是說,繼承自原型的屬性通過該操作符同樣會返回 true。

hasOwnProperty()

上面說過,通過構造函數創建的對象,預設都會存在內置的繼承結構,不管什麼對象,這個預設的繼承結構頂端都是構造函數 Object 的 prototype 屬性值,由於它的屬性值是一個內置的匿名對象,所以,通常都直接這麼表達,對象都會繼承自 Object.prototype,直接用 Object.prototype 的描述來代表這個屬性所指向的具體對象。

所以,以後在看到諸如某某對象繼承自 Function.prototype 或 Array.prototype 之類的描述,我們要能夠清楚,它表示的是,對象的原型是 xxxx.prototype 這屬性所指向的具體對象。

Object.prototype 屬性值指向的對象中,定義了一個 hasOwnProperty() 方法,所以基本所有對象都可以使用,它是用來判斷,對象是否含有指定的自有屬性的。

檢測屬性

首先利用上小節介紹的 in 方式來檢測,o 對象的預設繼承結構頂端是 Object.prototype,所以 o 對象繼承了它的 hasOwnProperty 屬性,第一行代碼返回 true。

這個 hasOwnProperty 屬性是個方法,調用它可以來檢測對象是否含有指定的自有屬性,參數也需要傳入屬性名的字元串格式,所以第二行代碼返回 false,第三行返回 true。

hasOwnProperty 是繼承自 Object.prototype 的屬性,由於 hasOwnProperty() 方法只能檢測自有屬性,所以第四行返回 false。

propertyIsEnumerable()

這個方法同樣是 Object.prototype 中所定義的方法,所以,同樣基本所有對象都能夠使用。

它是 hasOwnProperty() 的增強版,也就是,用於檢測對象的自有屬性且該屬性是可枚舉性的,才會返回 true。

可枚舉性是屬性的另一個特性,用來標識該屬性是否允許被遍歷,下麵會講解。

因為有一些內置屬性是不希望被枚舉出來的,所以可通過該方法來判斷。

遍歷屬性

遍歷屬性也稱枚舉屬性,也就是類似於對集合進行遍歷操作,將其所含有的屬性一個個讀取出來。

遍歷對象屬性的方式也有多種,也一一來介紹:

for-in 遍歷

var o = {name:"dasu"}
var o1 = Object.create(o);  //o1 繼承自 o
o1.age = 24;
o1.sex = "man";
o1.love = "girl";

for(p in o1) {
    console.log(p);    
}

看看輸出的結果:

遍歷屬性

o1 繼承自 o,在 o1 內有三個自有屬性,有一個繼承屬性,通過 for-in 方式遍歷對象 o1 的屬性時,不管是自有屬性,還是繼承屬性,都會被輸出。

同時,輸出的是屬性名,並不是屬性值,所以 for-in 方式只是遍歷對象的屬性(包括繼承屬性),並返回屬性名,註意是屬性名。

通常 for-in 這種方式,可以結合 hasOwnProperty() 方法一起使用,來過濾掉繼承的屬性。

Object.keys()

這又是一個類似靜態方法的存在,註意這個方法跟上述 Object.create() 都是構造函數 Object 上的方法,而普通對象繼承的是構造函數 Object.prototype 屬性值所指向的那個原型對象,這是兩個相互獨立的對象,也就是說,通過構造函數創建出來的子對象並不是繼承構造函數對象本身。

所以在子對象中,無法使用 Object.keys() 這類構造函數對象本身的屬性,這點需要註意一下,在後續專門講繼承時會再拿出來講講。

Object.keys()

參數傳入需要遍歷屬性的對象,通過該方法,可以獲得一個數組對象,數組內就存儲著參數傳入的對象的自有屬性且屬性是可枚舉性的,相當於 for-in 方式結合 hasOwnProperty() 的效果。

Object.getOwnPropertyNames()

該方法也是遍歷對象的自有屬性,只是它是將參數傳入的對象所擁有的所有屬性都輸出,包括那些被設置為不可枚舉的屬性,看個例子:

Object.getOwnPropertyNames

Object.prototype 指向了一個內置的對象,內置對象中定義了很多屬性,繼承這個原型的子對象們都可以使用這些屬性,但這些屬性都被設置為不可枚舉性,所以通過 Object.keys() 遍歷它時,得到的是一個空數組,子對象通過 for-in 方式遍歷時也讀取不到這些屬性。

這種設計是好的,但考慮到如果有某些場景是需要讀取對象自身的所有屬性,包括那些不可枚舉的,此時,就可通過 Object.getOwnPropertyNames() 來達到目的了。

屬性的特性

上面介紹中,或多或少有提到屬性的特性,屬性特性是指,屬性的一些特有行為。

屬性的特性一共有三個:可寫性、可配置性、可枚舉性

  • 可寫性:表示這個屬性是否允許被更改,當設置成 false 時,這就是一個只讀屬性
  • 可配置性:表示這個屬性是否允許被動態的添加或刪除,當設置成 false 時,就不允許通過 delete 來刪除
  • 可枚舉性:表示這個屬性是否允許在遍歷屬性過程中被讀取,當設置成 false 時,通過 for-in 或 Object.keys 都無法遍歷到這個屬性

那麼,如果知道對象的某個屬性的這三種特性都是什麼配置呢?

針對這種情況,內置了一個叫做屬性描述符的對象,這個對象本身含有四個屬性來描述屬性:value、writable、enumerable、configurable。

  • value:描述屬性值,即 key-value 中的 value
  • writable:描述屬性的可寫性
  • enumerable:描述屬性的可枚舉性
  • configurable:描述屬性的可配置性

用來描述屬性的數據結構有了,接下去就是如何操作了,先看一下,如果獲取對象某個屬性的描述信息:

Object.getOwnPropertyDescriptor()

還是通過Object 的一個方法,接收兩個參數,第一個參數是對象,第二個參數是對象內的某個自有屬性,將會返回一個屬性描述符對象:

Object.getOwnPropertyDescriptor

內置對象的很多屬性都會針對屬性的使用場景進行了不同的配置了,比如 Object.prototype 中所有屬性的 enumerable 可枚舉性都配置成 false。

但對於在代碼中,通過對象直接量創建的對象,或者自定義構造函數創建的對象等,對這些非內置對象添加的屬性,預設這三個特性都為 true,即對象添加的屬性預設都是可寫、可枚舉、可配置的。

Object.getOwnPropertyDescriptors()

這個方法也是用來獲取對象屬性的描述信息的,只是它只需一個參數即可,就是對象,然後會輸出所有自有屬性的描述信息:

Object.getOwnPropertyDescriptors

這兩個方法都是只能獲取對象的自有屬性的描述信息,如果想要獲取繼承屬性的描述信息,需要先獲取原型對象,再調用這兩個方法處理原型。獲取原型對象後續講原型時會介紹,這裡知道思路就可以了。

Object.defineProperty()

有獲取對象屬性的描述信息的方法,自然有設置對象屬性的描述信息方法,所以與上面兩個方法相對應的就是 Object.defineProperty() 方法和 Object.definproperties()。

Object.defineProperty() 接收三個參數,第一參數是對象,第二個參數是需要修改屬性描述信息的屬性,第三個參數是含有屬性描述符結構的對象:

var o = {name:"dasu"}
var o1 = Object.create(o);  //o1 繼承自 o
o1.age = 24;
o1.sex = "man";
o1.love = "girl";

Object.defineProperty(o1, "age", {writable:false});
Object.defineProperty(o1, "love", {enumerable:false, configurable:false});

第三個參數,你可以將四個屬性值都指定,沒指定的仍舊會使用預設的配置,再用 Object.getOwnPropertyDescriptors() 看下修改後的配置:

Object.defineProperty

Object.defineProperties()

這方法作用跟上面一樣,只是它是批量處理的方法,接收兩個參數,第一個是對象,第二個是需要修改的屬性集合,如:

var o = {name:"dasu"}
var o1 = Object.create(o);  //o1 繼承自 o
o1.age = 24;
o1.sex = "man";
o1.love = "girl";

Object.defineProperties(o1, {
    age: {writable:false},
    love:  {enumerable:false, configurable:false}
})

規則

有一些規則需要註意一下:

  • 如果屬性是不可配置的,那麼不能修改它的可配置性和可枚舉性,對於可寫性,只能將 true 改為 false,不能將 false 改為 true
  • 如果屬性是不可配置且不可寫的,那麼不能修改這個屬性的值
  • 如果屬性是可配置但不可寫的,那麼可以先將屬性修改成可寫,這時就可以修改屬性值

屬性的setter和getter

正常來說,對象的屬性由屬性的三種特性來控制屬性的操縱限制,但有一種情況是例外的,那就是通過 setter 和 getter 添加的屬性,這類屬性通常叫做存取器屬性,為了區分,將正常使用的那些屬性叫做數據屬性。

之所以叫做存取器屬性,是因為,通過這種方式添加的屬性,它的讀寫是交由 setter 和 getter 控制,並不是由屬性描述符的三種特性控制。

先來看下,如何定義一個存取器屬性:

var o = {
    set name(value) {},
    get name() {return "dasu"},
    
    get age() {return 24}
}

雖然看起來有點像 Java 中的 set 方法和 get 方法,但完全是兩種不一樣的東西,首先,這裡的 set 和 get 雖然類似方法,但外部是不能通過方法來調用,第二,外部訪問這些存取器屬性,仍舊是使用 .[] ,如 o.age 或 o["name"]。

相比於數據屬性,存取器屬性的區別就在於,讀和寫是通過 set 和 get 控制,在定義存取器屬性時,如果沒有定義 get,那麼這個屬性就是無法讀取的,如果沒有定義 set,那麼這個屬性就是不可寫的。其餘的,可枚舉性和可配置性都跟數據屬性一樣。

也一樣是通過 Object.defineProperty() 和 Object.getOwnPropertyDescriptor() 來設置或查看存取器屬性的描述信息,唯一需要註意的是,對於數據屬性,描述符對象有四個屬性:value,writable,enumerable,configurable;但對於存取器屬性來說,沒有 value 和 writable 屬性,與之替換的是 get 和 set 兩個屬性,所以看個例子:

var o = {
    set name(value) {},
    get name() {return "dasu"},  //存取器屬性,可讀,可寫,但讀寫邏輯得自己實現
    
    get age() {return 24},  //存取器屬性,只讀,讀的邏輯得自己寫
    
    sex: "man"  //數據屬性
}

假設定義了這麼個對象,有兩個存取器屬性,一個數據屬性,通過 Object.getOwnPropertyDescriptors() 看一下這些屬性的描述:

存取器屬性

所以存取器屬性和數據屬性就在於讀和寫這兩方面的不同,看下修改描述的方式:

存取器屬性.png

存取器屬性是可以換成數據屬性,同樣,數據屬性也是可以換成存取器屬性的,通過 Object.defineProperty() 在修改屬性描述信息時,使用的如果是 set 和 get,那就將數據屬性換成存取器屬性了,使用的如果是 value 和 writable,原本如果是存取器屬性,就將存取器屬性轉換成數據屬性了。

另外,它也有一些規則需要註意一下:

  • 如果存取器屬性是不可配置的,則不能修改 set 和 get 方法,也不能將它轉換為數據屬性
  • 如果數據屬性是不可配置的,則不能將它轉換為存取器屬性

對象的特性

對象的屬性有它的幾種特性,而對象本身也有一些特性,主要是三個:原型屬性、類屬性、可擴展性

原型屬性:表示對象繼承自哪個對象,被繼承的對象稱為子對象們的原型

類屬性:表示對象的類型信息,是一個字元串,比如數字的類屬性為 Number

可擴展性:表示是否允許對象可動態的添加屬性

原型留著後續講原型時再來細講,大概清楚對象是有繼承結構,被他繼承的對象稱作它的原型,所以通常說 JavaScript 是基於原型的繼承這些概念即可。

類屬性

類屬性,本質上就是通過調用 Object.toString() 方法來輸出對象的一些信息,這些信息中,包括了對象所屬類型的信息,對這串文本信息進行截取處理,就可以只獲取對象所屬類型的信息,所以稱這些信息為對象的類屬性。

類屬性所呈現的信息很類似於 typeOf 運算符所獲取的信息,只是類屬性會比 typeOf 更有用一些,它能夠區分所有的內置對象,以及區分 null,這些是 typeOf 所做不到的,如:

類屬性

可擴展性

類似於屬性有可配置性、可寫性、可枚舉性來控制屬性的操縱限制,對象也具有可擴展性來限制對象的一些行為。

當將對象的可擴展性設置為 false 時,就無法再動態的為對象添加屬性。預設創建的新對象,都是具有可擴展性的。

不像屬性的特性那樣,還專門定義了一個屬性描述符對象來控制屬性的特性,對於對象的可擴展性,操作很簡單:

Object.isExtensible()

使用 Object.isExtensible() 來獲取對象的可擴展性描述,返回 true,表示對象是可擴展的,即可動態添加屬性。

#### Object.preventExtensions()

同樣,可使用 Object.preventExtensions() 來設置對象的不可擴展,參數傳入對象即可。這樣,這個對象就不可動態添加屬性了。

但有幾點需要註意:

  • 一旦將對象設置為不可擴展,就無法再將其轉換回可擴展了
  • 可擴展性只限制於對象本身,對對象的原型並不影響,在原型上添加的屬性仍可動態同步到子對象上

針對於對象的可擴展性,對象屬性的可寫性、可配置性、可枚舉性這些操作,Object 內封裝了一些便捷的方法,如:

  • Object.seal():將對象設置為不可擴展,同時,將對象所有自有屬性都設置為不可配置,通常稱封閉對象。可用 Object.isSealed() 來檢測對象是否被封閉。
  • Object.freeze():將對象設置為不可擴展,同時,將對象所有自有屬性不可配置且只讀,通常稱凍結對象。可用 Object.isFrozen() 來檢測對象是否被凍結。

大家好,我是 dasu,歡迎關註我的公眾號(dasuAndroidTv),公眾號中有我的聯繫方式,歡迎有事沒事來嘮嗑一下,如果你覺得本篇內容有幫助到你,可以轉載但記得要關註,要標明原文哦,謝謝支持~
dasuAndroidTv2.png


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • "前言" 繼上一次webpack的基礎配置分享之後,本次將分享一些工作中項目常用的配置插件、也會包含一些自己瞭解過覺得不錯的插件,如有分析不到位的,歡迎糾錯, 嗯,這些東西文檔都有,大佬可繞過 。 Wepack4之後廢棄了很多的插件,這裡只會講解webpack4還支持的( ),已經廢棄的將不再闡述。 ...
  • 初來乍到,算是一個博客園的新人,受了園裡許多前輩的啟發正在一點點定製自己的小空間。 也希望我的文章能夠成為大家DIY的啟發,就算是拋磚引玉了。效果可以直接在我的博客中看到,所以不另外貼圖了。 引入js文件與css文件 引入js文件需要先申請js許可權,語言誠懇一點幾個小時(?)就可以拿到許可權了。 引入 ...
  • 上一篇寫的是左右寬高固定,中間自適應,根據上一篇的內容,總結了下上下寬高固定,中間自適應的幾種佈局方式,話不多說,直接上代碼。 下邊圖片是代碼運行的效果圖,大家可以運行代碼試試看。 自己總結的,有不對的地方歡迎大家指正! ...
  • 最近在開發一個網站時,有個需要是 如果有新預警信息要在網頁中播放提示音。頁面打開會請求是否有新信息,有則播放提示音。在Chrome的最新瀏覽器中,播放會報錯,控制台顯示Uncaught (in promise) DOMException: play() failed because the user ...
  • 事件的觸發權很多時候都屬於用戶,有些情況下會產生問題: 向後臺發送數據,用戶頻繁觸發,對伺服器造成壓力 一些瀏覽器事件:window.onresize、window.mousemove等,觸發的頻率非常高,會造成瀏覽器性能問題 如果你碰到這些問題,那就需要用到函數節流和防抖了。 一、函數節流(thr ...
  • 項目代碼 "從零開始簡書項目" ​ 從我第一次接觸 這個框架已經過了快一年的時間,陪伴我從前端小白到前端工程師,前端時間也是使用了 +`vue vue`這一塊,也算是比較熟練了,對底層也有一些瞭解,我開始了react的產生了一些興趣 ​ 第一次看 慕課網上的一個免費課程 "React 16實現訂單列 ...
  • nodejs 使用 js 模塊 Intro 最近需要用 nodejs 做一個爬蟲,Google 有一個 Puppeteer 的項目,可以用它來做爬蟲,有關 Puppeteer 的介紹網上也有很多,在這裡就不做詳細介紹了。 node 小白,開始的時候有點懵逼,模塊導出也不會。 官方文檔上說支持 .mj ...
  • 1.Js操作css樣式 div.style.width=”100px”.在div標簽內我們添加了一個style屬性,並設定 了width值。這種寫法會給標簽帶來大量的style屬性,跟實際項目是不符。 我們沒有讓css和html分離。 所以如果是為了獲取css樣式 window.getCompute ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...