摘要:通過這種操作,就有了構(gòu)造函數(shù)的原型對象里的方法。你也看到了,就是一個(gè)普通對象,所以這種寄生式繼承適合于根據(jù)已有對象創(chuàng)建一個(gè)加強(qiáng)版的對象,在主要考慮通過已有對象來繼承而不是構(gòu)造函數(shù)的情況下,這種方式的確很方便。
原文地址在我的博客, 轉(zhuǎn)載請注明出處,謝謝!
標(biāo)簽: [es5對象、原型, 原型鏈, 繼承]
什么是JavaScript對象注意(這篇文章特別長)
這篇文章僅僅是我個(gè)人對于JavaScript對象的理解,并不是教程。這篇文章寫于我剛了解js對象之后。文章肯定有錯(cuò)誤之處,還望讀者費(fèi)心指出,在下方評論即可^-^
var person = { //person就是對象,對象都有各種屬性,每個(gè)屬性又都對應(yīng)著自己的值 //鍵值對形式 name: "Mofan",//可以包含字符串 age: 20,//數(shù)字 parents: [ //數(shù)組 "Daddy", "Mami", ] sayName: function(){ //函數(shù) console.log(this.name); }, features: { //甚至是對象(很少用,我是沒見過) height: "178cm", weight: "60kg", } }
js里除了基本類型外所有事物都是對象:
函數(shù)是對象:function sayName(){} ——sayName是函數(shù)對象
數(shù)組是對象:var arr = new Array() ——arr是數(shù)組對象
為什么JavaScript要這么設(shè)計(jì)呢?我覺得首先這樣一來,統(tǒng)一了數(shù)據(jù)結(jié)構(gòu),使JavaScript成為一門編程風(fēng)格非常自由化的腳本語言:無論定義什么變量,統(tǒng)統(tǒng)var;其次,JavaScript對象都有屬性和方法,函數(shù)數(shù)組都是對象,調(diào)用引用就會(huì)非常靈活方便;再者,為了構(gòu)建原型鏈?
創(chuàng)建對象的幾種方式Object()模式
使用對象字面量:var obj={...}就像上面那樣,或者使用原生構(gòu)造函數(shù)Object():
var person = new Object(); person.name = "Mofan"; person.sayName = function(){ console.log(this.name); }; console.log(person.name);//Mofan obj.sayName();//Mofan
利用函數(shù)作用域使用自定義構(gòu)造函數(shù)模式模仿類(構(gòu)造器模式):
function Person(name,age){ this.name = name; this.age = age; this.print = function(){ console.log(this.name + this.age) }; } var person = new Person("Mofan",19); console.log(person.name+person.age);//Mofan19 person.print();//Mofan19
原型模式:
function Person(){} //可以這樣寫 /*Person.prototype.name = "Mofan"; Person.prototype.age = 19; Person.prototype.print = function(){ console.log(this.name+this.age); }*/ //推薦下面這樣寫,但兩種方式不能混用!因?yàn)橄旅孢@種方式實(shí)際上重寫了 //Person原型對象,如果兩者混用,后面賦值方式會(huì)覆蓋前面賦值方式 Person.prototype = { name:"Mofan", age:19, print:function(){ console.log(this.name+this.age); } } var person = new Person(); console.log(person.name+person.age);//Mofan19 person.print();//Mofan19
組合構(gòu)造函數(shù)模式和原型模式:
function Person(name,age){ //這里面初始化屬性 this.name = name; this.age = age; ... } Person.prototype = { //這里面定義公有方法 print:function(){ console.log(this.name+this.age); }, ... } var person = new Person("Mofan",19); console.log(person.name+person.age);//Mofan19 person.print();//Mofan19
動(dòng)態(tài)創(chuàng)建原型模式:
function Person(name,age){ //初始化屬性 this.name = name; this.age = age; //在創(chuàng)建第一個(gè)對象(第一次被調(diào)用)時(shí)定義所有公有方法,以后不再調(diào)用 if(typeof this.print !="function"){ Person.prototype.print =function(){ console.log(this.name+this.age); }; Person.prototype.introduction=function(){ console.log("Hi!I"m "+this.name+",I"m "+this.age); }; //如果采用對象字面量對原型添加方法的話,第一次創(chuàng)建的對象將不會(huì)有這些方法 }; } var person = new Person("Mofan",19); person.print();//Mofan19 person.introduction();//Hi!I"m Mofan,I"m 19
還有一些模式用的場景比較少
這些模式的應(yīng)用場景怎么會(huì)有這么多的創(chuàng)建模式?其實(shí)是因?yàn)閖s語言太靈活了,因此前輩們總結(jié)出這幾種創(chuàng)建方式以應(yīng)對不同的場景,它們各有利弊。
第一種方式,使用字面量或者使用構(gòu)造函數(shù)Object()常用于創(chuàng)建普通對象存儲(chǔ)數(shù)據(jù)等。它們的原型都是Object,彼此之間沒有什么關(guān)聯(lián)。事實(shí)上,下面創(chuàng)建方式都是一樣的:
var o1 = {};//字面量的表現(xiàn)形式 var o2 = new Object; var o3 = new Object(); var o4 = new Object(null); var o5 = new Object(undefined); var o6 = Object.create(Object.prototype);//等價(jià)于 var o = {};//即以 Object.prototype 對象為一個(gè)原型模板,新建一個(gè)以這個(gè)原型模板為原型的對象
第二種方式,利用函數(shù)作用域模仿類,這樣就可以在創(chuàng)建對象時(shí)傳參了,可以創(chuàng)建不同屬性值得對象,實(shí)現(xiàn)對象定制。不過print方法也定義在了構(gòu)造函數(shù)里面,如果要把它當(dāng)做公有方法的話,這樣每new一個(gè)對象,都會(huì)有這個(gè)方法,太浪費(fèi)內(nèi)存了。可以這樣修改一下構(gòu)造器模式:
//構(gòu)造器方法2 function print(){ //定義一個(gè)全局的 Function 對象,把要公有的方法拿出來 console.log(this.name + this.age); } function Person(name,age){ this.name = name; this.age = age; this.print = print.bind(this);//每個(gè) Person 對象共享同一個(gè)print 方法版本(方法有自己的作用域,不用擔(dān)心變量被共享) } var person = new Person("Mofan",19); console.log(person.name+person.age);//Mofan19 person.print();//Mofan19
然而這樣看起來很亂,也談不上類的封裝性。還是使用原型吧
第三種方式,純原型模式,不管是屬性還是方法都添加到原型里面去了,這樣做好處是很省內(nèi)存,但是應(yīng)用范圍就少了,更多的對象 內(nèi)部的屬性是需要定制的,而且一旦更改原型,所有這個(gè)原型實(shí)例都會(huì)跟著改變。因此可以結(jié)合構(gòu)造函數(shù)方式來實(shí)現(xiàn)對對象的定制,于是就有了第四種方式——組合構(gòu)造函數(shù)模式與原型模式,可以定制的放在構(gòu)造器里,共有的放在原型里,這也符合構(gòu)造器和原型的特性。
“這是es5中使用最廣泛、認(rèn)同度最高的創(chuàng)建自定義類型的方法”---《JavaScript高級(jí)程序設(shè)計(jì)》第三版
第五種方式,動(dòng)態(tài)原型模式,出現(xiàn)這種方式是因?yàn)橛行┟嫦驅(qū)ο箝_發(fā)人員習(xí)慣了類構(gòu)造函數(shù),于是對這種獨(dú)立出來的構(gòu)造函數(shù)和原型感到困惑和不習(xí)慣。于是,就出現(xiàn)了把定義原型也寫進(jìn)構(gòu)造函數(shù)里的動(dòng)態(tài)原型模式。
上面在動(dòng)態(tài)原型模式程序里面講“如果采用對象字面量對原型添加方法的話,第一次創(chuàng)建的對象將不會(huì)有這些方法”這是因?yàn)樵趇f語句執(zhí)行以前,第一個(gè)對象已經(jīng)被創(chuàng)建了,然后執(zhí)行if里面的語句,如果采用對象字面量給原型賦值,就會(huì)導(dǎo)致原型在實(shí)例創(chuàng)建之后被重寫,創(chuàng)建的第一個(gè)實(shí)例就會(huì)失去與原型的鏈接,也就沒有原型里的方法了。不過以后創(chuàng)建的對象就可以使用原型里的方法了,因?yàn)樗鼈兌际窃捅恍薷暮髣?chuàng)建的。
在JavaScript中,原型就是一個(gè)對象,沒必要把原型和其他對象區(qū)別對待,只是通過它可以實(shí)現(xiàn)對象之間屬性的繼承。任何一個(gè)對象也可以成為原型。之所以經(jīng)常說對象的原型,實(shí)際上就是想找對象繼承的上一級(jí)對象。對象與原型的稱呼是相對的,也就是說,一個(gè)對象,它稱呼繼承的上一級(jí)對象為原型,它自己也可以稱作原型鏈下一級(jí)對象的原型。
一個(gè)對象內(nèi)部的[[Prototype]]屬性生來就被創(chuàng)建,它指向繼承的上一級(jí)對象,稱為原型。函數(shù)對象內(nèi)部的prototype屬性也是生來就被創(chuàng)建(只有函數(shù)對象有prototype屬性),它指向函數(shù)的原型對象(不是函數(shù)的原型?。?。
當(dāng)使用var instance = new Class();這樣每new一個(gè)函數(shù)(函數(shù)被當(dāng)做構(gòu)造函數(shù)來使用)創(chuàng)建實(shí)例時(shí),JavaScript就會(huì)把這個(gè)原型的引用賦值給實(shí)例的原型屬性,于是實(shí)例內(nèi)部的[[Prototype]]屬性就指向了函數(shù)的原型對象,也就是prototype屬性。
原型真正意義上指的是一個(gè)對象內(nèi)部的[[Prototype]]屬性,而不是函數(shù)對象內(nèi)部的prototype屬性,這兩者之間沒有關(guān)系!對于一個(gè)對象內(nèi)部的[[Prototype]]屬性,不同瀏覽器有不同的實(shí)現(xiàn):
var a = {}; //Firefox 3.6+ and Chrome 5+ Object.getPrototypeOf(a); //[object Object] //Firefox 3.6+, Chrome 5+ and Safari 4+ a.__proto__; //[object Object] //all browsers a.constructor.prototype; //[object Object]
之所以函數(shù)對象內(nèi)部存在prototype屬性,并且可以用這個(gè)屬性創(chuàng)建一個(gè)原型,是因?yàn)檫@樣以來,每new一個(gè)這樣的函數(shù)(函數(shù)被當(dāng)做構(gòu)造函數(shù)來使用)創(chuàng)建實(shí)例,JavaScript就會(huì)把這個(gè)原型的引用賦值給實(shí)例的原型屬性,這樣以來,在原型中定義的方法等都會(huì)被所有實(shí)例共用,而且,一旦原型中的某個(gè)屬性被定義,就會(huì)被所有實(shí)例所繼承(就像上面的例子)。這種操作在性能和維護(hù)方面其意義是不言自明的。這也正是構(gòu)造函數(shù)存在的意義(JavaScript并沒有定義構(gòu)造函數(shù),更沒有區(qū)分構(gòu)造函數(shù)和普通函數(shù),是開發(fā)人員約定俗成)。下面是一些例子:
var a = {} //一個(gè)普通的對象 function fun(){} //一個(gè)普通的函數(shù) //普通對象沒有prototype屬性 console.log(a.prototype);//undefined console.log(a.__proto__===Object.prototype);//true //只有函數(shù)對象有prototype屬性 console.log(fun.prototype);//Object console.log(fun.__proto__===Function.prototype);//true console.log(fun.prototype.__proto__===Object.prototype);//true console.log(fun.__proto__.__proto__===Object.prototype);//true console.log(Function.prototype.__proto__===Object.prototype);//true console.log(Object.prototype.__proto__);//null
當(dāng)執(zhí)行console.log(fun.prototype);輸出為
可以看到,每創(chuàng)建一個(gè)函數(shù),就會(huì)創(chuàng)建prototype屬性,這個(gè)屬性指向函數(shù)的原型對象(不是函數(shù)的原型),并且這個(gè)原型對象會(huì)自動(dòng)獲得constructor屬性,這個(gè)屬性是指向prototype屬性所在函數(shù)的指針。而__proto__屬性是每個(gè)對象都有的。
接著上面再看:
function Person(){}//構(gòu)造函數(shù),約定首字母大寫 var person1 = new Person();//person1為Person的實(shí)例 console.log(person1.prototype);//undefined console.log(person1.__proto__===Person.prototype);//true console.log(person1.__proto__.__proto__===Object.prototype);//true console.log(person1.constructor);//function Person(){} //函數(shù)Person是Function構(gòu)造函數(shù)的實(shí)例 console.log(Person.__proto__===Function.prototype);//true //Person的原型對象是構(gòu)造函數(shù)Object的實(shí)例 console.log(Person.prototype.__proto__===Object.prototype);//true
person1和上面那個(gè)普通的對象a有區(qū)別,它是構(gòu)造函數(shù)Person的實(shí)例。前面講過:
當(dāng)使用var instance = new Class();這樣每new一個(gè)函數(shù)(函數(shù)被當(dāng)做構(gòu)造函數(shù)來使用)創(chuàng)建實(shí)例時(shí),JavaScript就會(huì)把這個(gè)原型的引用賦值給實(shí)例的原型屬性,于是實(shí)例內(nèi)部的[[Prototype]]屬性就指向了函數(shù)的原型對象,也就是prototype屬性。
因此person1內(nèi)部的[[Prototype]]屬性就指向了Person的原型對象,然后Person的原型對象內(nèi)部的[[Prototype]]屬性再指向Object.prototype,相當(dāng)于在原型鏈中加了一個(gè)對象。通過這種操作,person1就有了構(gòu)造函數(shù)的原型對象里的方法。
另外,上面代碼console.log(person1.constructor);//function Person(){}中,person1內(nèi)部并沒有constructor屬性,它只是順著原型鏈往上找,在person1.__proto__里面找到的。
可以用下面這張圖理清原型、構(gòu)造函數(shù)、實(shí)例之間的關(guān)系:
JavaScript并沒有繼承這一現(xiàn)有的機(jī)制,但可以利用函數(shù)、原型、原型鏈模仿。
下面是三種繼承方式:
//父類 function SuperClass(){ this.superValue = "super"; } SuperClass.prototype.getSuperValue = function(){ return this.superValue; }; //子類 function SubClass(){ this.subValue = "sub"; } //類式繼承,將父類實(shí)例賦值給子類原型,子類原型和子類實(shí)例可以訪問到父類原型上以及從父類構(gòu)造函數(shù)中復(fù)制的屬性和方法 SubClass.prototype = new SuperClass(); //為子類添加方法 SubClass.prototype.getSubValue = function(){ return this.subValue; } //使用 var instance = new SubClass(); console.log(instance.getSuperValue);//super console.log(instance.getSubValue);//sub
這種繼承方式有很明顯的兩個(gè)缺點(diǎn):
實(shí)例化子類時(shí)無法向父類構(gòu)造函數(shù)傳參
如果父類中的共有屬性有引用類型,就會(huì)在子類中被所有實(shí)例所共用,那么任何一個(gè)子類的實(shí)例更改這個(gè)引用類型就會(huì)影響其他子類實(shí)例,可以使用構(gòu)造函數(shù)繼承方式解決這一問題
構(gòu)造函數(shù)繼承//父類 function SuperClass(id){ this.superValue = ["big","large"];//引用類型 this.id = id; } SuperClass.prototype.getSuperValue = function(){ return this.superValue; }; //子類 function SubClass(id){ SuperClass.call(this,id);//調(diào)用父類構(gòu)造函數(shù)并傳參 this.subValue = "sub"; } var instance1 = new SubClass(10);//可以向父類傳參 var instance2 = new SubClass(11); instance1.superValue.push("super"); console.log(instance1.superValue);//["big", "large", "super"] console.log(instance1.id);//10 console.log(instance2.superValue);["big", "large"] console.log(instance2.id);//11 console.log(instance1.getSuperValue());//error
這種方式是解決了類式繼承的缺點(diǎn),不過在代碼的最后一行你也看到了,沒有涉及父類原型,因此違背了代碼復(fù)用的原則。所以組合它們:
組合繼承function SuperClass(id){ this.superValue = ["big","large"];//引用類型 this.id = id; } SuperClass.prototype.getSuperValue = function(){ return this.superValue; }; //子類 function SubClass(id,subValue){ SuperClass.call(this,id);//調(diào)用父類構(gòu)造函數(shù)并傳參 this.subValue = subValue; } SubClass.prototype = new SuperClass(); SubClass.prototype.getSubValue = function(){ return this.subValue; } var instance1 = new SubClass(10,"sub");//可以向父類傳參 var instance2 = new SubClass(11,"sub-sub"); instance1.superValue.push("super"); console.log(instance1.superValue);//["big", "large", "super"] console.log(instance1.id);//10 console.log(instance2.superValue);["big", "large"] console.log(instance2.id);//11 console.log(instance1.getSuperValue());["big", "large", "super"] console.log(instance1.getSubValue());//sub console.log(instance2.getSuperValue());//["big", "large"] console.log(instance2.getSubValue());//sub-sub
嗯,比較完美了,但是有一點(diǎn),父類構(gòu)造函數(shù)被調(diào)用了兩次,這就導(dǎo)致第二次調(diào)用也就是創(chuàng)建實(shí)例時(shí)重寫了原型屬性,原型和實(shí)例都有這些屬性,顯然性能并不好。先來看看克羅克福德的寄生式繼承:
function object(o){ function F(){}; F.prototype = o; return new F(); } function createAnnther(original){ var clone = object(original); clone.sayName = function(){ console.log(this.name); } return clone; } var person = { name:"Mofan", friends:["xiaoM","Alice","Neo"], }; var anotherPerson = createAnnther(person); anotherPerson.sayName();//"Mofan" }
就是讓一個(gè)已有對象變成新對象的原型,然后再在createAnother函數(shù)里加強(qiáng)。你也看到了,person就是一個(gè)普通對象,所以這種寄生式繼承適合于根據(jù)已有對象創(chuàng)建一個(gè)加強(qiáng)版的對象,在主要考慮通過已有對象來繼承而不是構(gòu)造函數(shù)的情況下,這種方式的確很方便。但缺點(diǎn)也是明顯的,createAnother函數(shù)不能復(fù)用,我如果想給另外一個(gè)新創(chuàng)建的對象定義其他方法,還得再寫一個(gè)函數(shù)。仔細(xì)觀察一下,其實(shí)寄生模式就是把原型給了新對象,對象再加強(qiáng)。
等等,寫到這個(gè)地方,我腦子有點(diǎn)亂,讓我們回到原點(diǎn):繼承的目的是什么?應(yīng)該繼承父類哪些東西?我覺得取決于我們想要父類的什么,我想要父類全部的共有屬性(原型里)并且可以自定義繼承的父類私有屬性(構(gòu)造函數(shù)里)!前面那么多模式它們的缺點(diǎn)主要是因?yàn)檫@個(gè):
SubClass.prototype = new SuperClass();
那為什么要寫這一句呢?是只想要繼承父類的原型嗎?如果是為什么不這么寫:
SubClass.prototype = SuperClass.prototype;
這樣寫是可以繼承父類原型,但是風(fēng)險(xiǎn)極大:SuperClass.prototype屬性它是一個(gè)指針,指向SuperClass的原型,如果把這個(gè)指針賦給子類prototype屬性,那么子類prototype也會(huì)指向父類原型。對SubClass.prototype任何更改,就是對父類原型的更改,這顯然是不行的。
寄生組合式繼承但出發(fā)點(diǎn)沒錯(cuò),可以換種繼承方式,看看上面的寄生式繼承里的object()函數(shù),如果把父類原型作為參數(shù),它返回的對象實(shí)現(xiàn)了對父類原型的繼承,沒有調(diào)用父類構(gòu)造函數(shù),也不會(huì)對父類原型產(chǎn)生影響,堪稱完美。
function object(o){ function F(){}; F.prototype = o; return new F(); } function inheritPrototype(subType,superType){ var proto = object(superType.prototype); proto.constructor = subType;//矯正一下construcor屬性 subType.prototype = proto; } function SuperClass(id){ this.superValue = ["big","large"];//引用類型 this.id = id; } SuperClass.prototype.getSuperValue = function(){ return this.superValue; }; //子類 function SubClass(id,subValue){ SuperClass.call(this,id);//調(diào)用父類構(gòu)造函數(shù)并傳參 this.subValue = subValue; } inheritPrototype(SubClass,SuperClass);//繼承父類原型 SubClass.prototype.getSubValue = function(){ return this.subValue; } var instance1 = new SubClass(10,"sub");//可以向父類傳參 var instance2 = new SubClass(11,"sub-sub"); instance1.superValue.push("super"); console.log(instance1.superValue);//["big", "large", "super"] console.log(instance1.id);//10 console.log(instance2.superValue);//["big", "large"] console.log(instance2.id);//11 console.log(instance1.getSuperValue());//["big", "large", "super"] console.log(instance1.getSubValue());//sub console.log(instance2.getSuperValue());//["big", "large"] console.log(instance2.getSubValue());//sub-sub
解決了組合繼承的問題,只調(diào)用了一次父類構(gòu)造函數(shù),而且還能保持原型鏈不變,為什么這么說,看對寄生組合的測試:
console.log(SubClass.prototype.__proto__===SuperClass.prototype);//ture console.log(SubClass.prototype.hasOwnProperty("getSuperValue"));//false
因此,這是引用類型最理想的繼承方式。
總結(jié)創(chuàng)建用于繼承的對象最理想的方式是組合構(gòu)造函數(shù)模式和原型模式(或者動(dòng)態(tài)原型模式),就是讓可定義的私有屬性放在構(gòu)造函數(shù)里,共有的放在原型里;繼承最理想的方式是寄生式組合,就是讓子類的原型的[[prototype]]屬性指向父類原型,然后在子類構(gòu)造函數(shù)里調(diào)用父類構(gòu)造函數(shù)實(shí)現(xiàn)自定義繼承的父類屬性。
JavaScript對象總有一些讓我困惑的地方,不過我還會(huì)繼續(xù)探索。我在此先把我了解的記錄下來,與各位共勉。錯(cuò)誤的地方請費(fèi)心指出,我將感謝您的批評指正。
本文為作者原創(chuàng),轉(zhuǎn)載請注明本文鏈接,作者保留權(quán)利。
參考文獻(xiàn):
[1] http://www.cnblogs.com/chuaWe...
[2] http://www.cnblogs.com/xjser/...
[3] https://javascriptweblog.word...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/88985.html
摘要:匿名函數(shù)的執(zhí)行環(huán)境具有全局性,因此它的對象通常指向。如果對此有疑惑,可以看知乎上的答案知乎匿名函數(shù)的指向?yàn)槭裁词亲鳛閷ο蠓椒ǖ恼{(diào)用,指向該對象當(dāng)函數(shù)作為某個(gè)對象的方法調(diào)用時(shí),就指這個(gè)函數(shù)所在的對象。 因?yàn)槿粘9ぷ髦薪?jīng)常使用到this,而且在JavaScript中this的指向問題也很容易讓人混淆一部分知識(shí)。 這段時(shí)間翻閱了一些書籍也查閱了網(wǎng)上一些資料然后結(jié)合自己的經(jīng)驗(yàn),為了能讓自...
摘要:因?yàn)槲覀冇眠@個(gè)函數(shù)來構(gòu)造對象,所以我們也把稱作構(gòu)造函數(shù)。所以通過定義構(gòu)造函數(shù),就相當(dāng)于定義了一個(gè)類,通過關(guān)鍵字,即可生成一個(gè)實(shí)例化的對象。 一、序言 ??和其他面向?qū)ο蟮恼Z言(如Java)不同,Javascript語言對類的實(shí)現(xiàn)和繼承的實(shí)現(xiàn)沒有標(biāo)準(zhǔn)的定義,而是將這些交給了程序員,讓程序員更加靈活地(當(dāng)然剛開始也更加頭疼)去定義類,實(shí)現(xiàn)繼承。(以下不討論ES6中利用class、exten...
摘要:這兩個(gè)函數(shù)接受定時(shí)器的例如我們上面提到的兩個(gè)函數(shù)產(chǎn)生的定時(shí)器,并停止對定時(shí)器中指定函數(shù)的調(diào)用。注意,定時(shí)器雖然觸發(fā)了,但是并不會(huì)立即執(zhí)行,它只是把需要延遲執(zhí)行的函數(shù)加入了執(zhí)行隊(duì)列,在線程的某一個(gè)可用的時(shí)間點(diǎn),這個(gè)函數(shù)就能夠得到執(zhí)行。 擼了今年阿里、頭條和美團(tuán)的面試,我有一個(gè)重要發(fā)現(xiàn)....... javascript定時(shí)器工作原理是一個(gè)重要的基礎(chǔ)知識(shí)點(diǎn)。因?yàn)槎〞r(shí)器在單線程中工作,它們表...
摘要:本課程之所以叫做闖關(guān)記,是因?yàn)椴糠终鹿?jié)精心設(shè)計(jì)了挑戰(zhàn)關(guān)卡,通過提供更多的實(shí)戰(zhàn)機(jī)會(huì),讓大家可以循序漸進(jìn)地有目的地有挑戰(zhàn)地開展學(xué)習(xí)。課程結(jié)構(gòu)及目錄以下目錄只是初步構(gòu)想,課程結(jié)構(gòu)及內(nèi)容會(huì)根據(jù)實(shí)際情況隨時(shí)進(jìn)行調(diào)整。 為何寫作此課程 stone 主要負(fù)責(zé)基于 Web 的企業(yè)內(nèi)部管理系統(tǒng)的開發(fā),雖然能夠熟練地使用 JavaScript,但隨著對 JavaScript 的理解越來越深,才發(fā)現(xiàn)自己尚...
摘要:函數(shù)式編程一開始我并不理解。漸漸地,我熟練掌握了使用函數(shù)式的方法去編程。但是自從學(xué)習(xí)了函數(shù)式編程,我將循環(huán)都改成了使用和來實(shí)現(xiàn)。只有數(shù)據(jù)和函數(shù),而且因?yàn)楹瘮?shù)沒有和對象綁定,更加容易復(fù)用。在函數(shù)式的中,這些問題不復(fù)存在。 譯者按: 當(dāng)從業(yè)20的JavaScript老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了90%的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛啊?。?! 原文: How I rediscov...
閱讀 1727·2021-11-11 10:58
閱讀 4217·2021-09-09 09:33
閱讀 1268·2021-08-18 10:23
閱讀 1558·2019-08-30 15:52
閱讀 1634·2019-08-30 11:06
閱讀 1877·2019-08-29 14:03
閱讀 1517·2019-08-26 14:06
閱讀 2969·2019-08-26 10:39