js對象實(shí)例詳解(JavaScript對象深度剖析,深度理解js對象)
這算是醞釀很久的一篇文章了。
JavaScript作為一個(gè)基于對象(沒有類的概念)的語言,從入門到精通到放棄一直會被對象這個(gè)問題圍繞。
平時(shí)發(fā)的文章基本都是開發(fā)中遇到的問題和對最佳解決方案的探討,終于忍不住要寫一篇基礎(chǔ)概念類的文章了。
本文探討以下問題,在座的朋友各取所需,歡迎批評指正:
1、創(chuàng)建對象
2、__proto__與prototype
3、繼承與原型鏈
4、對象的深度克隆
5、一些Object的方法與需要注意的點(diǎn)
6、ES6新增特性
下面反復(fù)提到實(shí)例對象和原型對象,通過構(gòu)造函數(shù) new 出來的本文稱作 實(shí)例對象,構(gòu)造函數(shù)的原型屬性本文稱作 原型對象。
創(chuàng)建對象
字面量的方式:
var myHonda = {color: "red", wheels: 4, engine: {cylinders: 4, size: 2.2}}
就是new Object()的語法糖,一樣一樣的。
工廠模式:
function createCar(){ var oTemp = new Object(); oTemp.name = arguments[0]; //直接給對象添加屬性,每個(gè)對象都有直接的屬性 oTemp.age = arguments[1]; oTemp.showName = function () { alert(this.name); };//每個(gè)對象都有一個(gè) showName 方法版本 return oTemp; }; var myHonda = createCar('honda', 5)
只是給new Object()包了層皮,方便量產(chǎn),并沒有本質(zhì)區(qū)別,姑且算作創(chuàng)建對象的一種方式。
構(gòu)造函數(shù):
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; this.getName = function() { return this.name; }; } var rand = new Person("Rand McKinnon", 33, "M");
上面構(gòu)造函數(shù)的 getName 方法,每次實(shí)例化都會新建該函數(shù)對象,還形成了在當(dāng)前情況下并沒有卵用的閉包,所以構(gòu)造函數(shù)添加方法用下面方式處理,工廠模式給對象添加方法的時(shí)候也應(yīng)該用下面的方式避免重復(fù)構(gòu)造函數(shù)對象
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; this.getName = getName } function getName() { return this.name; };
構(gòu)造函數(shù)創(chuàng)建對象的過程和工廠模式又是半斤八兩,相當(dāng)于隱藏了創(chuàng)建新對象和返回該對象這兩步,構(gòu)造函數(shù)內(nèi) this 指向新建對象,沒什么不同。
最大不同點(diǎn): 構(gòu)造函數(shù)創(chuàng)造出來的對象 constructor 屬性指向該構(gòu)造函數(shù),工廠模式指向 function Object(){...}。
構(gòu)造函數(shù)相當(dāng)于給原型鏈上加了一環(huán),構(gòu)造函數(shù)有自己的 prototype,工廠模式就是個(gè)普通函數(shù)。說到這兒我上一句話出現(xiàn)了漏洞,工廠模式的 constructor 指向哪得看第一句話 new 的是什么。
構(gòu)造函數(shù)直接調(diào)用而不 new 的話,就看調(diào)用時(shí)候 this 指向誰了,直接調(diào)用就把屬性綁到 window 上了,通過 call 或者 apply 綁定到其他對象作用域就把屬性添加到該對象了。
原型模式:
構(gòu)造函數(shù)雖然在原型鏈上加了一環(huán),但顯然這一環(huán)啥都沒有啊,這樣一來和工廠模式又有什么區(qū)別?加了一環(huán)又有什么意義?原型模式浮出水面。
function Car(){} //用空構(gòu)造函數(shù)設(shè)置類名 Car.prototype.color = "blue";//每個(gè)對象都共享相同屬性 Car.prototype.doors = 3; Car.prototype.drivers = new Array("Mike","John"); Car.prototype.showColor = function(){ alert(this.color); };//每個(gè)對象共享一個(gè)方法版本,省內(nèi)存。 //構(gòu)造函數(shù)的原型屬性可以通過字面量來設(shè)置,別忘了通過 Object.defineProperty()設(shè)置 constructor 為該構(gòu)造函數(shù) function Car(){} Car.prototype = { color:"blue", doors:3, showColor:function(){ alert(this.color); } } Object.defineProperty(Car.prototype, "constructor", { enumerable:false, value:Car }) //(不設(shè)置 constructor 會導(dǎo)致 constructor 不指向構(gòu)造函數(shù),直接設(shè)置 constructor 會導(dǎo)致 constructor 可枚舉)
使用原型模式注意動(dòng)態(tài)性,通過構(gòu)造函數(shù)實(shí)例化出的對象,他的原型對象是構(gòu)造函數(shù)的 prototype ,如果在他的原型對象上增加或刪除一些方法,該對象會繼承這些修改。例如,先通過構(gòu)造函數(shù) A 實(shí)例化出對象 a ,然后再給 A.prototype 添加一個(gè)方法,a 是可以繼承這個(gè)方法的。但是給 A.prototype 設(shè)置一個(gè)新的對象,a 是不會繼承這個(gè)新對象的屬性和方法的。聽起來有點(diǎn)繞,修改 A.prototype 相當(dāng)于直接修改 a 的原型對象,a 很自然的會繼承這些修改,但是重新給 A.prototype 賦值的話,修改的是構(gòu)造函數(shù)的原型,并沒有影響 a 的原型對象!a 被創(chuàng)建出來以后原型對象就已經(jīng)確定了,除非直接修改這個(gè)原型對象(或者這個(gè)原型對象的原型對象),否則 a 是不會繼承這些修改的!
Object.create()
傳入要?jiǎng)?chuàng)建對象實(shí)例的原型對象,和原型模式幾乎是一個(gè)意思也是相當(dāng)于在原型鏈上加了一環(huán),區(qū)別在于這種方式創(chuàng)建的對象沒有構(gòu)造函數(shù)。這種方式相當(dāng)于:
function object(o){ function F(){} F.prototype = o; return new F() }
相當(dāng)于構(gòu)造函數(shù)只短暫的存在了一會,創(chuàng)建出來的對象的 constructor 指向 原型對象 o 的 constructor !
混合模式:
使用原型模式時(shí),當(dāng)給實(shí)例對象設(shè)置自己專屬的屬性的時(shí)候,該實(shí)例對象會忽略原型鏈中的該屬性。但當(dāng)原型鏈中的屬性是引用類型值的時(shí)候,操作不當(dāng)有可能會直接修改原型對象的屬性!這會影響到所有使用該原型對象的實(shí)例對象!
大部分情況下,實(shí)例對象的多數(shù)方法是共有的,多數(shù)屬性是私有的,所以屬性在構(gòu)造函數(shù)中設(shè)置,方法在原型中設(shè)置是合適的,構(gòu)造函數(shù)與原型結(jié)合使用是通常的做法。
還有一些方法,無非是工廠模式與構(gòu)造函數(shù)與原型模式的互相結(jié)合,在生成過程和 this 指向上做一些小變化。
class 方式:
見下面 ES6 class 部分,只是一個(gè)語法糖,本質(zhì)上和構(gòu)造函數(shù)并沒有什么區(qū)別,但是繼承的方式有一些區(qū)別。
proto與prototype
這兩個(gè)到底是什么關(guān)系?搞清楚 實(shí)例對象 構(gòu)造函數(shù) 原型對象 的三角關(guān)系,這兩個(gè)屬性的用法就自然清晰了,順便說下 constructor。
構(gòu)造函數(shù)創(chuàng)建的實(shí)例對象的 constructor 指向該構(gòu)造函數(shù)(但實(shí)際上 constructor 是對應(yīng)的原型對象上的一個(gè)屬性!所以實(shí)例對象的 constructor 是繼承來的,這一點(diǎn)要注意,如果利用原型鏈繼承,constructor 將有可能指向原型對象的構(gòu)造函數(shù)甚至更上層的構(gòu)造函數(shù),其他重寫構(gòu)造函數(shù) prototype 的行為也會造成 constructor 指向問題,都需要重設(shè) constructor),構(gòu)造函數(shù)的 prototype 指向?qū)?yīng)的原型對象,實(shí)例對象的 __proto__ 指對應(yīng)的原型對象,__proto__是瀏覽器的實(shí)現(xiàn),并沒有出現(xiàn)在標(biāo)準(zhǔn)中,可以用 constructor.prototype 代替??紤]到 Object.create() 創(chuàng)建的對象,更安全的方法是 Object.getPrototpyeOf() 傳入需要獲取原型對象的實(shí)例對象。
我自己都感覺說的有點(diǎn)亂,但是他們就是這樣的,上一張圖,看看能不能幫你更深刻理解這三者關(guān)系。
繼承與原型鏈
當(dāng)訪問一個(gè)對象的屬性時(shí),如果在對象本身找不到,就會去搜索對象的原型,原型的原型,知道原型鏈的盡頭 null,那原型鏈?zhǔn)窃趺存溒饋淼模?/p>
把 實(shí)例對象 構(gòu)造函數(shù) 原型對象 視為一個(gè)小組,上面說了三者互相之間的關(guān)系,構(gòu)造函數(shù)是函數(shù),可實(shí)例對象和原型對象可都是普通對象啊,這就出現(xiàn)了這樣的情況:
這個(gè)小組的原型對象,等于另一個(gè)小組實(shí)例對象,而此小組的原型對象又可能是其他小組的實(shí)例對象,這樣一個(gè)個(gè)的小組不就連接起來了么。舉個(gè)例子:
function Super(){ this.val = 1; this.arr = [1]; } function Sub(){ // ... } Sub.prototype = new Super();
Sub 是一個(gè)小組 Super 是一個(gè)小組,Sub 的原型對象鏈接到了 Super 的實(shí)例對象。
基本上所有對象順著原型鏈爬到頭都是 Object.prototype , 而 Object.prototype 就沒有原型對象,原型鏈就走到頭了。
判斷構(gòu)造函數(shù)和原型對象是否存在于實(shí)例對象的原型鏈中:
實(shí)例對象 instanceof 構(gòu)造函數(shù),返回一個(gè)布爾值,原型對象.isPrototypeOf(實(shí)例對象),返回一個(gè)布爾值。
上面是最簡單的繼承方式了,但是有兩個(gè)致命缺點(diǎn):
所有 Sub 的實(shí)例對象都繼承自同一個(gè) Super 的實(shí)例對象,我想傳參數(shù)到 Super 怎么辦?
如果 Super 里有引用類型的值,比如上面例子中我給 Sub 的實(shí)例對象中的 arr 屬性 push 一個(gè)值,豈不是牽一發(fā)動(dòng)全身?
下面說一種最常用的組合繼承模式,先舉個(gè)例子:
function Super(value){ // 只在此處聲明基本屬性和引用屬性 this.val = value; this.arr = [1]; } // 在此處聲明函數(shù) Super.prototype.fun1 = function(){}; Super.prototype.fun2 = function(){}; //Super.prototype.fun3... function Sub(value){ Super.call(this,value); // 核心 // ... } Sub.prototype = new Super(); // 核心
過程是這樣的,在簡單的原型鏈繼承的基礎(chǔ)上, Sub 的構(gòu)造函數(shù)里運(yùn)行 Super ,從而給 Sub 的每一個(gè)實(shí)例對象一份單獨(dú)的屬性,解決了上面兩個(gè)問題,可以給 Super 傳參數(shù)了,而且因?yàn)槭仟?dú)立的屬性,不會因?yàn)檎`操作引用類型值而影響其他實(shí)例了。不過還有個(gè)小缺點(diǎn): Sub 中調(diào)用的 Super 給每個(gè) Sub 的實(shí)例對象一套新的屬性,覆蓋了繼承的 Super 實(shí)例對象的屬性,那被覆蓋的的那套屬性不就浪費(fèi)了?豈不是白繼承了?最嚴(yán)重的問題是 Super 被執(zhí)行了兩次,這不能忍(其實(shí)也沒多大問題)。下面進(jìn)行一下優(yōu)化,把上面例子最后一行替換為:
Sub.prototype = Object.create(Super.prototype); // Object.create() 給原型鏈上添加一環(huán),否則 Sub 和 Super 的原型就重疊了。 Sub.prototype.constructor = Sub;
到此為止,繼承非常完美。
其他還有各路繼承方式無非是在 簡單原型鏈繼承 --> 優(yōu)化的組合繼承 路程之間的一些思路或者封裝。
通過 class 繼承的方式:
通過 class 實(shí)現(xiàn)繼承的過程與 ES5 完全相反,詳細(xì)見下面 ES6 class的繼承 部分。
對象的深度克隆
JavaScript的基礎(chǔ)類型是值傳遞,而對象是引用傳遞,這導(dǎo)致一個(gè)問題:
克隆一個(gè)基礎(chǔ)類型的變量的時(shí)候,克隆出來的的變量是和舊的變量完全獨(dú)立的,只是值相同而已。
而克隆對象的時(shí)候就要分兩種情況了,簡單的賦值會讓兩個(gè)變量指向同一塊內(nèi)存,兩者代表同一個(gè)對象,甚至算不上克隆克隆。但我們常常需要的是兩個(gè)屬性和方法完全相同但卻完全獨(dú)立的對象,稱為深度克隆。我們接下來討論幾種深度克隆的方法。
說幾句題外的話,業(yè)界有一個(gè)非常知名的庫 immutable ,個(gè)人認(rèn)為很大程度上解決了深度克隆的痛點(diǎn),我們修改一個(gè)對象的時(shí)候,很多時(shí)候希望得到一個(gè)全新的對象(比如Redux每次都要用一個(gè)全新的對象修改狀態(tài)),由此我們就需要進(jìn)行深度克隆。而 immutable 相當(dāng)于產(chǎn)生了一種新的對象類型,每一次修改屬性都會返回一個(gè)全新的 immutable 對象,免去了我們深度克隆的工作是小事,關(guān)鍵性能特別好。
歷遍屬性
function clone(obj){ var newobj = obj.constructor === Array ? [] : {}; // 用 instanceof 判斷也可 if(typeof obj !== 'object' || obj === null ){ return obj } else { for(var i in obj){ newobj[i] = typeof obj[i] === 'object' ? cloneObj(obj[i]) : obj[i]; // 只考慮 對象和數(shù)組, 函數(shù)雖然也是引用類型,但直接賦值并不會產(chǎn)生什么副作用,所以函數(shù)類型無需深度克隆。 } } return newobj; };
原型式克隆
function clone(obj){ function F() {}; F.prototype = obj; var f = new F(); for(var key in obj) { if(typeof obj[key] =="object") { f[key] = clone(obj[key]) } } return f ; }
這種方式不能算嚴(yán)格意義上的深度克隆,并沒有切斷新對象與被克隆對象的聯(lián)系,被克隆對象作為新對象的原型存在,雖然新對象的改變不會影響舊對象,但反之則不然!而且給新對象屬性重新賦值的時(shí)候只是覆蓋了原型中的屬性,在歷遍新對象的時(shí)候也會出現(xiàn)問題。這種方式問題重重,除了實(shí)現(xiàn)特殊目的可以酌情使用,通常情況應(yīng)避免使用。
json序列化
var newObj = JSON.parse(JSON.stringify(obj));
這是我最喜歡的方式了!簡短粗暴直接!但是最大的問題是,畢竟JSON只是一種數(shù)據(jù)格式所以這種方式只能克隆屬性,不能克隆方法,方法在序列化以后就消失了。。。
一些Object的方法與需要注意的點(diǎn)
Object 自身的方法:
設(shè)置屬性,Object.defineProperty(obj, prop, descriptor) 根據(jù) descriptor 定義 obj 的 prop 屬性(值,是否可寫可枚舉可刪除等)。
Object.getOwnPropertyDescriptor(obj, prop) 返回 obj 的 prop 屬性的描述。
使對象不可拓展,Object.preventExtensions(obj),obj 將不能添加新的屬性。
判斷對像是否可拓展,Object.isExtensible(obj)。
密封一個(gè)對象,Object.seal(obj),obj 將不可拓展且不能刪除已有屬性。
判斷對象是否密封,Object.isSealed(obj)。
凍結(jié)對象,Object.freeze(obj) obj 將被密封且不可修改。
判斷對象是否凍結(jié),Object.isFrozen(obj)。
獲取對象自身屬性(包括不可枚舉的),Object.getOwnPropertyNames(obj),返回 obj 所有自身屬性組成的數(shù)組。
獲取對象自身屬性(不包括不可枚舉的),Object.keys(obj),返回 obj 所有自身可枚舉屬性組成的數(shù)組。
當(dāng)使用for in循環(huán)遍歷對象的屬性時(shí),原型鏈上的所有可枚舉屬性都將被訪問。
只關(guān)心對象本身時(shí)用Object.keys(obj)代替 for in,避免歷遍原型鏈上的屬性。
獲取某對象的原型對象,Object.getPrototypeOf(object),返回 object 的原型對象。
設(shè)置某對象的原型對象,Object.setPrototypeOf(obj, prototype),ES6 新方法,設(shè)置 obj 的原型對象為 prototype ,該語句比較耗時(shí)。
Object.prototype 上的方法:
檢查對象上某個(gè)屬性是否存在時(shí)(存在于本身而不是原型鏈中),obj.hasOwnProperty() 是唯一可用的方法,他不會向上查找原型鏈,只在 obj 自身查找,返回布爾值。
檢測某對象是否存在于參數(shù)對象的原型鏈中,obj.isPrototypeOf(obj2),obj 是否在 obj2 的原型鏈中,返回布爾值。
檢測某屬性是否是對象自身的可枚舉屬性,obj.propertyIsEnumerable(prop),返回布爾值。
對象類型,obj.toString(),返回 "[object type]" type 可以是 Date,Array,Math 等對象類型。
obj.valueOf(),修改對象返回值時(shí)的行為,使用如下:
function myNumberType(n) { this.number = n; } myNumberType.prototype.valueOf = function() { return this.number; }; myObj = new myNumberType(4); myObj + 3; // 7
ES6新增特性
判斷兩個(gè)值是否完全相等,Object.is(value1, value2),類似于 === 但是可以用來判斷 NaN。
屬性和方法簡寫:
// 屬性簡寫 var foo = 'bar'; var baz = {foo}; baz // {foo: "bar"} // 等同于 var baz = {foo: foo}; // 方法簡寫 function f(x, y) { return {x, y}; } // 等同于 function f(x, y) { return {x: x, y: y}; } f(1, 2) // Object {x: 1, y: 2}
合并對象:
Object.assign(target, [...source]);
將 source 中所有和枚舉的屬性復(fù)制到 target。
多個(gè) source 對象有同名屬性,后面的覆蓋前面的。
var target = { a: 1 }; var source1 = { b: 2 }; var source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
注意一點(diǎn),該命令執(zhí)行的是淺克隆,如果 source 中有屬性是對象,target 中會復(fù)制該對象的引用。
常用于給對象添加屬性和方法(如給構(gòu)造函數(shù)的原型添加方法),克隆、合并對象等。
獲取對象自身的值或鍵值對(做為Object.keys(obj)的補(bǔ)充不包括不可枚舉的):
Object.keys(obj)返回 obj 自身所有可枚舉屬性的值組成的數(shù)組。
Object.entries(obj)返回 obj 自身所有可枚舉鍵值對數(shù)組組成的數(shù)組,例如:
var obj = { foo: 'bar', baz: 42 }; Object.entries(obj) // [ ["foo", "bar"], ["baz", 42] ] // 可用于將對象轉(zhuǎn)為 Map 結(jié)構(gòu) var obj = { foo: 'bar', baz: 42 }; var map = new Map(Object.entries(obj)); map // Map { foo: "bar", baz: 42 }
拓展運(yùn)算符:
取出對象所有可歷遍屬性,舉例:
let z = { a: 3, b: 4 }; let n = { ...z }; n // { a: 3, b: 4 } // 可代替 Object.assign() let ab = { ...a, ...b }; // 等同于 let ab = Object.assign({}, a, b);
可用于解構(gòu)賦值中最后一個(gè)參數(shù):
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; x // 1 y // 2 z // { a: 3, b: 4 } // 可以這樣理解,把 z 拆開以后就等于后面對象未被分配出去的鍵值對。
Null 傳導(dǎo)運(yùn)算符:
const firstName = message?.body?.user?.firstName || 'default'; // 代替 const firstName = (message && message.body && message.body.user && message.body.user.firstName) || 'default';
class:
ES6 引入了 class 關(guān)鍵字,但并沒有改變對象基于原型繼承的原理,只是一個(gè)語法糖,讓他長得像傳統(tǒng)面向?qū)ο笳Z言而已。
以下兩個(gè)寫法完全等價(jià):
function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; //定義類 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } // 類中定義的方法就是在原型上
有兩點(diǎn)區(qū)別, class 中定義的方法是不可枚舉的,class 必須通過 new 調(diào)用不能直接運(yùn)行。
class 不存在變量提升,使用要在定義之后。
class 中的方法前加 static 關(guān)鍵字定義靜態(tài)方法,只能通過 class 直接調(diào)用不能被實(shí)例繼承。
如果靜態(tài)方法包含 this 關(guān)鍵字,這個(gè) this 指的是 class,而不是實(shí)例。注意下面代碼:
class Foo { static bar () { this.baz(); } static baz () { console.log('hello'); } baz () { console.log('world'); } } Foo.bar() // hello
父類的靜態(tài)方法,可以被子類繼承,目前 class 內(nèi)部無法定義靜態(tài)屬性。
設(shè)置靜態(tài)屬性與實(shí)例屬性新提案:
class 的實(shí)例屬性可以用等式,寫入類的定義之中。
靜態(tài)屬性直接前面加 static 即可。
class MyClass { myProp = 42; static myStaticProp = 42; }
class 的繼承:
class 通過 extends 實(shí)現(xiàn)繼承,注意 super 關(guān)鍵字
class ColorPoint extends Point { constructor(x, y, color) { super(x, y); // 調(diào)用父類的constructor(x, y) this.color = color; } toString() { return this.color + ' ' + super.toString(); // 調(diào)用父類的toString() } }
extends 可以繼承其他類或任何有 prototype 屬性的函數(shù)。
super 會從父類獲取各路信息綁定到子類的 this。
子類自己沒有 this 對象,要先繼承父類的實(shí)例對象然后再進(jìn)行加工,所以要在 constructor 里調(diào)用 super 繼承 this 對象后才能使用 this。
ES5 的繼承,實(shí)質(zhì)是先創(chuàng)造子類的實(shí)例對象 this,然后再將父類的方法添加到 this 上面(Parent.apply(this))。ES6 的繼承機(jī)制完全不同,實(shí)質(zhì)是先創(chuàng)造父類的實(shí)例對象 this(所以必須先調(diào)用 super 方法創(chuàng)建和繼承這個(gè) this,并綁定到子類的 this),然后再用子類的構(gòu)造函數(shù)修改this。
這條理由也是造成了 ES6 之前無法繼承原生的構(gòu)造函數(shù)(Array Function Date 等)的原型對象,而使用 class 可以。因?yàn)?ES5 中的方法是先實(shí)例化子類,再把父類的屬性添加上去,但是父類有很多不能直接訪問的屬性或方法,這就糟了,而通過 class 繼承反其道而行之先實(shí)例化父類,這就自然把所有屬性和方法都繼承了。
super 作為對象時(shí),在普通方法中,指向父類的原型對象;在靜態(tài)方法中,指向父類。
通過 super 調(diào)用父類的方法時(shí),super 會綁定子類的 this。
constructor 方法會被默認(rèn)添加:
class ColorPoint extends Point { } // 等同于 class ColorPoint extends Point { constructor(...args) { super(...args); } }
Object.getPrototypeOf(object),獲取某對象的原型對象,也可以獲取某類的原型類。
class 的 __proto__與prototype
子類的__proto__屬性,表示構(gòu)造函數(shù)的繼承,總是指向父類。
子類prototype屬性的__proto__屬性,表示方法的繼承,總是指向父類的 prototype 屬性。
相當(dāng)于子類本身繼承父類,子類的原型對象繼承自父類的原型對象。
new.target:
用在構(gòu)造函數(shù)或者 class 內(nèi)部,指向調(diào)用時(shí) new 的構(gòu)造函數(shù)或者 class。
以上這篇js對象實(shí)例詳解(JavaScript對象深度剖析,深度理解js對象)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
js中symbol類型以及symbol的三大應(yīng)用場景詳解
Symbol是ES6新推出的一種基本類型,它表示獨(dú)一無二的值,它可以接受一個(gè)字符串作為參數(shù),帶有相同參數(shù)的兩個(gè)Symbol值不相等,這個(gè)參數(shù)只是表示Symbol值的描述而已,下面這篇文章主要給大家介紹了關(guān)于js中symbol類型以及symbol的三大應(yīng)用場景,需要的朋友可以參考下2022-09-09JavaScript?的setTimeout與事件循環(huán)機(jī)制event-loop
這篇文章主要介紹了JavaScript?的setTimeout與事件循環(huán)機(jī)制event-loop,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07JavaScript實(shí)現(xiàn)點(diǎn)擊切換驗(yàn)證碼及校驗(yàn)
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)點(diǎn)擊切換驗(yàn)證碼及校驗(yàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01js實(shí)現(xiàn)方塊上下左右移動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)方塊上下左右移動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08javascript實(shí)現(xiàn)延時(shí)顯示提示框效果
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)延時(shí)顯示提示框效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06純javascript實(shí)現(xiàn)自動(dòng)發(fā)送郵件
當(dāng)我們發(fā)送郵件時(shí),可以自定義郵件發(fā)送的時(shí)間,那么使用代碼是如何實(shí)現(xiàn)的呢?下面通過本篇文章給大家介紹使用純javascript實(shí)現(xiàn)自動(dòng)發(fā)送郵件,感興趣的朋友可以參考下2015-10-10D3.js的基礎(chǔ)部分之?dāng)?shù)組的處理數(shù)組的排序和求值(v3版本)
這篇文章主要介紹了D3.js的基礎(chǔ)部分之?dāng)?shù)組的處理數(shù)組的排序和求值(v3版本) ,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05js核心基礎(chǔ)之構(gòu)造函數(shù)constructor用法實(shí)例分析
這篇文章主要介紹了js核心基礎(chǔ)之構(gòu)造函數(shù)constructor用法,結(jié)合具體實(shí)例形式分析了javascript構(gòu)造函數(shù)constructor概念、原理、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-05-05