摘要:運(yùn)算符用來測試一個(gè)對象在其原型鏈中是否存在一個(gè)構(gòu)造函數(shù)的屬性。全局變量在頁面關(guān)閉后銷毀。同理,待第行執(zhí)行完畢,即函數(shù)執(zhí)行完畢后,調(diào)用函數(shù)所生成的上下文環(huán)境出棧,并且被銷毀已經(jīng)用完了,就要及時(shí)銷毀,釋放內(nèi)存。
1. JavaScript的數(shù)據(jù)類型 1.1 JavaScript有幾種類型的值
基本類型(值類型)
字符串(String)
數(shù)字(Number)
布爾(Boolean)
對空(Null)
未定義(Undefined)
獨(dú)一無二的值(Symbol)
引用類型
對象(Object)
數(shù)組(Array)
函數(shù)(Function)
...
1.2 基本數(shù)據(jù)類型 1.2.1 值是不可變的var name = "jie"; name.toUpperCase(); console.log(name); //jie1.2.2 存放在棧區(qū)
基本數(shù)據(jù)類型直接存儲(chǔ)在棧(stack)中的簡單數(shù)據(jù)段
為什么放入棧中存儲(chǔ)
占據(jù)空間小
大小固定
屬于被頻繁使用數(shù)據(jù)
1.2.3 值的比較var a = 1; var b = true; console.log(a == b) //true console.log(a === b); //false
== : 只進(jìn)行值的比較,會(huì)進(jìn)行數(shù)據(jù)類型的轉(zhuǎn)換。
=== : 不僅進(jìn)行值得比較,還要進(jìn)行數(shù)據(jù)類型的比較。
1.3 引用數(shù)據(jù)類型 1.3.1 值是可變的var a = { age: 20 } var b = a; b.age = 21; console.log(a.age) //21 console.log(b.age) //211.3.2 同時(shí)保存在棧內(nèi)存和堆內(nèi)存
引用數(shù)據(jù)類型存儲(chǔ)在堆(heap)中的對象,占據(jù)空間大、大小不固定,如果存儲(chǔ)在棧中,將會(huì)影響程序運(yùn)行的性能;
引用數(shù)據(jù)類型在棧中存儲(chǔ)了指針,該指針指向堆中該實(shí)體的起始地址
當(dāng)解釋器尋找引用值時(shí),會(huì)首先檢索其在棧中的地址,取得地址后從堆中獲得實(shí)體。
1.3.3比較是引用的比較var a = { age: 20 } var b = a; b.age = 21; console.log(a.age) //21 console.log(b.age) //21
變量a初始化時(shí),a指針指向?qū)ο髙age:20}的地址,a賦值給b后,b又指向該對象{age:20}的地址,這兩個(gè)變量指向了同一個(gè)對象。因此,改變其中任何一個(gè)變量,都會(huì)相互影響。
如果取消某一個(gè)變量對于原對象的引用,不會(huì)影響到另一個(gè)變量
var a = { age: 20 } var b = a; a = 1; console.log(a) //1 console.log(b) //{age:20}
a和b指向同一個(gè)對象,然后a的值變?yōu)?,這時(shí)不會(huì)對b產(chǎn)生影響,b還是指向原來的那個(gè)對象。
2.JavaScript檢測 2.1 typeoftypeof返回一個(gè)表示數(shù)據(jù)類型的字符串,返回結(jié)果包括:number、boolean、string、symbol、object、undefined、function等7種數(shù)據(jù)類型,
但不能判斷null、array
typeof Symbol(); // symbol 有效 typeof ""; // string 有效 typeof 1; // number 有效 typeof true; //boolean 有效 typeof undefined; //undefined 有效 typeof new Function(); // function 有效 typeof null; //object 無效 typeof [] ; //object 無效 typeof new Date(); //object 無效 typeof new RegExp(); //object 無效2.2 instanceof
instanceof 是用來判斷A是否為B的實(shí)例,表達(dá)式為:A instanceof B,如果A是B的實(shí)例,則返回true,否則返回false。
instanceof 運(yùn)算符用來測試一個(gè)對象在其原型鏈中是否存在一個(gè)構(gòu)造函數(shù)的 prototype 屬性。
不能檢測null 和 undefined
[] instanceof Array; //true {} instanceof Object;//true new Date() instanceof Date;//true new RegExp() instanceof RegExp//true2.3 constructor
null 和 undefined 是無效的對象,因此是不會(huì)有 constructor 存在的,這兩種類型的數(shù)據(jù)需要通過其他方式來判斷
2.4Object.prototype.toString.call()Object.prototype.toString.call("") ; // [object String] Object.prototype.toString.call(1) ; // [object Number] Object.prototype.toString.call(true) ; // [object Boolean] Object.prototype.toString.call(undefined) ; // [object Undefined] Object.prototype.toString.call(null) ; // [object Null] Object.prototype.toString.call(new Function()) ; // [object Function] Object.prototype.toString.call(new Date()) ; // [object Date] Object.prototype.toString.call([]) ; // [object Array] Object.prototype.toString.call(new RegExp()) ; // [object RegExp] Object.prototype.toString.call(new Error()) ; // [object Error] Object.prototype.toString.call(document) ; // [object HTMLDocument] Object.prototype.toString.call(window) ; //[object global] window是全局對象global的引用2.5 參考
https://github.com/ljianshu/B...
3. 函數(shù)(方法) 3.1 生成函數(shù)的三種方式 3.1.1 函數(shù)聲明function fn(){ console.log("aa") } fn()3.1.2 函數(shù)表達(dá)式
var fn = function() { console.log("aa") } fn()3.1.3 立即執(zhí)行函數(shù)
var i = "aa"; (function(i) { console.log(i) //aa })(i)
function fn(i) { (function() { console.log(i) //aa })() } fn("aa")
function fn() { (function(i) { console.log(i) // undefined })() } fn("aa")
function fn() { (function() { console.log(i) })(i) } fn("aa")3.2 函數(shù)的作用域
函數(shù)的作用域分為全局作用
3.2.1先聲明變量,再調(diào)用方法var a = "aa" fn() function fn() { var b = "bb" c = "cc" console.log(a) //aa console.log(b) //bb console.log(c) //cc } console.log(a) //a console.log(c) //cc console.log(b) //b is not defined3.2.先調(diào)用方法,再聲明變量
fn() var a = "aa" function fn() { var b = "bb" c = "cc" console.log(a) //aa console.log(b) //bb console.log(c) //cc } console.log(a) //undefined console.log(b) //b is not defined console.log(c) //cc3.3 變量生命周期
JavaScript 變量生命周期在它聲明時(shí)初始化。
局部變量在函數(shù)執(zhí)行完畢后銷毀。
全局變量在頁面關(guān)閉后銷毀。
4. 原型到原型鏈 為什么會(huì)存在因?yàn)閖s要實(shí)現(xiàn)繼承,js沒有像別的語言有繼承這個(gè)東西(es6中的class本質(zhì)上也是基于原型和原型鏈),
4.1名詞解釋constructor 構(gòu)造函數(shù)
prototype 原型(顯式原型),只有函數(shù)才有 prototype 屬性
__proto__ 原型鏈(隱式原型),每一個(gè)JavaScript對象(除了 null )都具有的一個(gè)屬性,函數(shù)也是對象,所以函數(shù)也有__proto__
4.2 構(gòu)造函數(shù)創(chuàng)建對象 4.2.1最簡單的構(gòu)造函數(shù)函數(shù)名字為大寫
與new配合
Person 就是一個(gè)構(gòu)造函數(shù),我們使用 new 創(chuàng)建了一個(gè)實(shí)例對象 person
function Person() { } var person = new Person(); person.name = "jie" console.log(person.name)4.2.2 prototype(原型)
那什么是原型呢
每一個(gè)JavaScript對象(null除外)在創(chuàng)建的時(shí)候就會(huì)與之關(guān)聯(lián)另一個(gè)對象,這個(gè)對象就是我們所說的原型,每一個(gè)對象都會(huì)從原型"繼承"屬性
每個(gè)函數(shù)都有一個(gè) prototype 屬性
函數(shù)的 prototype 屬性指向了一個(gè)對象,這個(gè)對象正是調(diào)用該構(gòu)造函數(shù)而創(chuàng)建的實(shí)例的原型,也就是這個(gè)例子中的 person1 和 person2 的原型
function Person() { } Person.prototype.name = "jie" var person1 = new Person(); var person2 = new Person(); console.log(person1.name) //jie console.log(person2.name) //jie
用一張圖表示構(gòu)造函數(shù)和實(shí)例原型之間4.2.3 proto
每一個(gè)JavaScript對象(除了 null )都具有的一個(gè)屬性,叫__proto__,
這個(gè)屬性會(huì)指向該對象的原型
function Person() { } var person = new Person(); console.log(person.__proto__ === Person.prototype) //true
用一張圖表示實(shí)例和實(shí)例原型之間的__proto__4.2.4 constructor
每個(gè)原型都有一個(gè) constructor 屬性指向關(guān)聯(lián)的構(gòu)造函數(shù)
function Person() { } console.log(Person === Person.prototype.constructor) //true4.3 實(shí)例與原型
當(dāng)讀取實(shí)例的屬性時(shí),如果找不到,就會(huì)查找與對象關(guān)聯(lián)的原型中的屬性
如果還查不到,就去找原型的原型,一直找到最頂層為止
function Person() { } Person.prototype.name = "原型上的名字"; var person1 = new Person(); var person2 = new Person(); person1.name = "實(shí)例名字1"; person2.name = "實(shí)例名字2"; console.log("person1.name:" + person1.name) //實(shí)例名字1 console.log("person2.name:" + person2.name) //實(shí)例名字2 delete person1.name; console.log("person1.name:" + person1.name) //原型上的名字 console.log("person2.name:" + person2.name) //實(shí)例名字14.4 原型的原型
原型也是一個(gè)對象,既然是對象,我們就可以用最原始的方式創(chuàng)建它
var obj = new Object(); obj.name = "jie" console.log(obj.name)4.5 原型鏈
function Person() { } var p1 = new Person(); console.log(p1.__proto__ === Person.prototype) //true console.log(Person.prototype.__proto__ === Object.prototype) //true console.log(Object.prototype.__proto__ === null) //true
圖中由相互關(guān)聯(lián)的原型組成的鏈狀結(jié)構(gòu)就是原型鏈,也就是藍(lán)色的這條線。
4.6 其它 4.6.1 person.constructorfunction Person() { } var person = new Person(); console.log(person.constructor === Person); // true
當(dāng)獲取 person.constructor 時(shí),其實(shí) person 中并沒有 constructor 屬性,當(dāng)不能讀取到constructor 屬性時(shí),會(huì)從 person 的原型也就是 Person.prototype 中讀取,正好原型中有該屬性,所以:
person.constructor === Person.prototype.constructor4.6.2 真的是繼承嗎
繼承意味著復(fù)制操作,然而 JavaScript 默認(rèn)并不會(huì)復(fù)制對象的屬性,相反,JavaScript 只是在兩個(gè)對象之間創(chuàng)建一個(gè)關(guān)聯(lián),這樣,一個(gè)對象就可以通過委托訪問另一個(gè)對象的屬性和函數(shù),所以與其叫繼承,委托的說法反而更準(zhǔn)確些
4.7 參考https://github.com/mqyqingfen...
5.詞法作用域JavaScript 采用詞法作用域(lexical scoping),也就是靜態(tài)作用域
var value = 1; function fn1() { console.log(value) } function fn2() { var value = 2; fn1() } fn2()
按照函數(shù)棧先進(jìn)后出的順序執(zhí)行,先執(zhí)行完fn1(),再執(zhí)行完fn2()
執(zhí)行 fn1 函數(shù),先從 fn1 函數(shù)內(nèi)部查找是否有局部變量 value,如果沒有,就根據(jù)書寫的位置(),查找上面一層的代碼,也就是 value 等于 1,所以結(jié)果會(huì)打印 1
6.執(zhí)行上下文 6.1 聲明(創(chuàng)建) JavaScript 變量使用 var 關(guān)鍵詞來聲明變量
var carname;
變量聲明之后,該變量是空的(它沒有值)。
如需向變量賦值,請使用等號:
carname="Volvo";
不過,您也可以在聲明變量時(shí)對其賦值:
var carname="Volvo";6.2 變量聲明的各種情況 6.2.1 打印未聲明和未賦值
console.log(a)6.2.2 先打印,再聲明和未賦值
console.log(a) //undefined var a;6.2.3 先打印,再聲明和未賦值
console.log(a) //undefined var a = 10;6.2.4 聲明和未賦值,再打印,
var a = 10; console.log(a)6.3 函數(shù)聲明的各種情況 6.3.1 函數(shù)聲明
console.log(f1) function f1() { }6.3.2 函數(shù)表達(dá)式
console.log(f2) var f2 = function() { }6.4 this
console.log(this)6.5 什么是執(zhí)行上下文
執(zhí)行上下文也叫做執(zhí)行上下文環(huán)境
給執(zhí)行上下文環(huán)境下一個(gè)通俗的定義:在執(zhí)行代碼之前,把將要用到的所有的變量都事先拿出來,有的直接賦值了,有的先用undefined占個(gè)空
變量、函數(shù)表達(dá)式——變量聲明,默認(rèn)賦值為undefined;
this——賦值;
函數(shù)聲明——賦值;
這三種數(shù)據(jù)的準(zhǔn)備情況我們稱之為“執(zhí)行上下文”或者“執(zhí)行上下文環(huán)境”
6.6 函數(shù)中的執(zhí)行上下文以下代碼展示了在函數(shù)體的語句執(zhí)行之前,arguments變量和函數(shù)的參數(shù)都已經(jīng)被賦值。從這里可以看出,函數(shù)每被調(diào)用一次,都會(huì)產(chǎn)生一個(gè)新的執(zhí)行上下文環(huán)境。因?yàn)椴煌恼{(diào)用可能就會(huì)有不同的參數(shù)
function fn(x) { console.log(arguments) console.log(x) } fn(10) fn(20)6.6 總結(jié)
全局代碼的上下文環(huán)境數(shù)據(jù)內(nèi)容為
普通變量(包括函數(shù)表達(dá)式),如: var a = 10; | 聲明(默認(rèn)賦值為undefined) |
---|---|
函數(shù)聲明,如: function fn() { } | 賦值 |
this | 賦值 |
如果代碼段是函數(shù)體,那么在此基礎(chǔ)上需要附加
參數(shù) | 賦值 |
---|---|
arguments | 賦值 |
自由變量的取值作用域 | 賦值 |
http://www.cnblogs.com/wangfu...
7.執(zhí)行上下文棧 7.1 什么是執(zhí)行上下文棧執(zhí)行全局代碼時(shí),會(huì)產(chǎn)生一個(gè)執(zhí)行上下文環(huán)境,每次調(diào)用函數(shù)都又會(huì)產(chǎn)生執(zhí)行上下文環(huán)境。當(dāng)函數(shù)調(diào)用完成時(shí),這個(gè)上下文環(huán)境以及其中的數(shù)據(jù)都會(huì)被消除,再重新回到全局上下文環(huán)境。處于活動(dòng)狀態(tài)的執(zhí)行上下文環(huán)境只有一個(gè)
這是一個(gè)壓棧出棧的過程——執(zhí)行上下文棧
在執(zhí)行代碼之前,首先將創(chuàng)建全局上下文環(huán)境
然后是代碼執(zhí)行。代碼執(zhí)行到第12行之前,上下文環(huán)境中的變量都在執(zhí)行過程中被賦值。
執(zhí)行到第13行,調(diào)用bar函數(shù)。
跳轉(zhuǎn)到bar函數(shù)內(nèi)部,執(zhí)行函數(shù)體語句之前,會(huì)創(chuàng)建一個(gè)新的執(zhí)行上下文環(huán)境。
并將這個(gè)執(zhí)行上下文環(huán)境壓棧,設(shè)置為活動(dòng)狀態(tài)
執(zhí)行到第5行,又調(diào)用了fn函數(shù)。進(jìn)入fn函數(shù),在執(zhí)行函數(shù)體語句之前,會(huì)創(chuàng)建fn函數(shù)的執(zhí)行上下文環(huán)境,并壓棧,設(shè)置為活動(dòng)狀態(tài)。
待第5行執(zhí)行完畢,即fn函數(shù)執(zhí)行完畢后,此次調(diào)用fn所生成的上下文環(huán)境出棧,并且被銷毀(已經(jīng)用完了,就要及時(shí)銷毀,釋放內(nèi)存)。
同理,待第13行執(zhí)行完畢,即bar函數(shù)執(zhí)行完畢后,調(diào)用bar函數(shù)所生成的上下文環(huán)境出棧,并且被銷毀(已經(jīng)用完了,就要及時(shí)銷毀,釋放內(nèi)存)。
8. this 8.1 判斷分析當(dāng)前this對于直接調(diào)用 foo 來說,不管 foo 函數(shù)被放在了什么地方,this 一定是 window
對于 obj.foo() 來說,我們只需要記住,誰調(diào)用了函數(shù),誰就是 this,所以在這個(gè)場景下 foo 函數(shù)中的 this 就是 obj 對象
在構(gòu)造函數(shù)模式中,類中(函數(shù)體中)出現(xiàn)的this.xxx=xxx中的this是當(dāng)前類的一個(gè)實(shí)例
call、apply和bind:this 是第一個(gè)參數(shù)
箭頭函數(shù)this指向:箭頭函數(shù)沒有自己的this,看其外層的是否有函數(shù),如果有,外層函數(shù)的this就是內(nèi)部箭頭函數(shù)的this,如果沒有,則this是window。
8.2 this的5種情況 8.2.1 直接調(diào)用foo()function foo() { console.log(this) } var a = 1; foo()8.2.2 obj.foo()
function fn() { console.log(this) } var obj = { fn: fn } obj.fn();8.2.3 構(gòu)造函數(shù)
function CreateJsPerson(name, age) { //this是當(dāng)前類的一個(gè)實(shí)例p1 this.name = name; //=>p1.name=name this.age = age; //=>p1.age=age console.log(this) } var p1 = new CreateJsPerson("尹華芝", 48);8.2.4 call、apply和bind
function add(c, d) { console.log(this) return this.a + this.b + c + d; } var o = { a: 1, b: 3 }; add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 348.2.5 箭頭函數(shù)
8.3 參考
https://github.com/ljianshu/B...
9. 作用域和上下文環(huán)境作用域在函數(shù)定義時(shí)就已經(jīng)確定了。而不是在函數(shù)調(diào)用時(shí)確定
9.1 程序執(zhí)行時(shí)的,上下文環(huán)境按照程序執(zhí)行的順序,一步一步把各個(gè)上下文環(huán)境
在加載程序時(shí),已經(jīng)確定了全局上下文環(huán)境,并隨著程序的執(zhí)行而對變量就行賦值
程序執(zhí)行到第27行,調(diào)用fn(10),此時(shí)生成此次調(diào)用fn函數(shù)時(shí)的上下文環(huán)境,壓棧,并將此上下文環(huán)境設(shè)置為活動(dòng)狀態(tài)。
行到第23行時(shí),調(diào)用bar(100),生成此次調(diào)用的上下文環(huán)境,壓棧,并設(shè)置為活動(dòng)狀態(tài)
執(zhí)行完第23行,bar(100)調(diào)用完成。則bar(100)上下文環(huán)境被銷毀。接著執(zhí)行第24行,調(diào)用bar(200),則又生成bar(200)的上下文環(huán)境,壓棧,設(shè)置為活動(dòng)狀態(tài)。
執(zhí)行完第24行,則bar(200)調(diào)用結(jié)束,其上下文環(huán)境被銷毀。此時(shí)會(huì)回到fn(10)上下文環(huán)境,變?yōu)榛顒?dòng)狀態(tài)。
執(zhí)行完第27行代碼,fn(10)執(zhí)行完成之后,fn(10)上下文環(huán)境被銷毀,全局上下文環(huán)境又回到活動(dòng)狀態(tài)。
9.2 參考http://www.cnblogs.com/wangfu...
10. 自由變量到作用域鏈 10.1 自由變量在A作用域中使用的變量x,卻沒有在A作用域中聲明(即在其他作用域中聲明的),對于A作用域來說,x就是一個(gè)自由變量
var x = 10; function fn() { var b = 20; console.log(x + b) //這里的x在這里就是一個(gè)自由變量 }
而取x的值時(shí),就需要到另一個(gè)作用域中取。到哪個(gè)作用域中取呢?
要到創(chuàng)建這個(gè)函數(shù)的那個(gè)作用域中取值——是“創(chuàng)建”,而不是“調(diào)用”,切記切記
var x = 10; function fn() { console.log(x) //10 } function show(f) { var x = 20; (function() { f() })() } show(fn)10.2 作用域鏈
如果跨了一步,還沒找到呢?——接著跨!——一直跨到全局作用域?yàn)橹埂R窃谌肿饔糜蛑卸紱]有找到,那就是真的沒有了。
這個(gè)一步一步“跨”的路線,我們稱之為——作用域鏈
取自由變量時(shí)的這個(gè)“作用域鏈”過程:(假設(shè)a是自由量)
現(xiàn)在當(dāng)前作用域查找a,如果有則獲取并結(jié)束。如果沒有則繼續(xù);
如果當(dāng)前作用域是全局作用域,則證明a未定義,結(jié)束;否則繼續(xù);
不是全局作用域,那就是函數(shù)作用域)將創(chuàng)建該函數(shù)的作用域作為當(dāng)前作用域;
跳轉(zhuǎn)到第一步。
實(shí)例
第13行,fn()返回的是bar函數(shù),賦值給x。執(zhí)行x(),即執(zhí)行bar函數(shù)代碼。取b的值時(shí),直接在fn作用域取出。取a的值時(shí),試圖在fn作用域取,但是取不到,只能轉(zhuǎn)向創(chuàng)建fn的那個(gè)作用域中去查找,結(jié)果找到了。
11. 閉包 11.1 什么是閉包閉包是指可以訪問另一個(gè)函數(shù)作用域變量的函數(shù),一般是定義在外層函數(shù)中的內(nèi)層函數(shù)。11.2 為什么需要閉包呢
局部變量無法共享和長久的保存,而全局變量可能造成變量污染,所以我們希望有一種機(jī)制既可以長久的保存變量又不會(huì)造成全局污染。
11.3 特點(diǎn)占用更多內(nèi)存
不容易被釋放
11.4作用保護(hù)
保存
11.5 何時(shí)使用既想反復(fù)使用,又想避免全局污染
11.6 如何使用定義外層函數(shù),封裝被保護(hù)的局部變量。
定義內(nèi)層函數(shù),執(zhí)行對外部函數(shù)變量的操作。
外層函數(shù)返回內(nèi)層函數(shù)的對象,并且外層函數(shù)被調(diào)用,結(jié)果保存在一個(gè)全局的變量中。
11.7 實(shí)例代碼執(zhí)行前生成全局上下文環(huán)境,并在執(zhí)行時(shí)對其中的變量進(jìn)行賦值。此時(shí)全局上下文環(huán)境是活動(dòng)狀態(tài)
執(zhí)行第17行代碼時(shí),調(diào)用fn(),產(chǎn)生fn()執(zhí)行上下文環(huán)境,壓棧,并設(shè)置為活動(dòng)狀態(tài)。
執(zhí)行完第17行,fn()調(diào)用完成
按理說應(yīng)該銷毀掉fn()的執(zhí)行上下文環(huán)境,但是這里不能這么做。注意,重點(diǎn)來了:因?yàn)閳?zhí)行fn()時(shí),返回的是一個(gè)函數(shù)。函數(shù)的特別之處在于可以創(chuàng)建一個(gè)獨(dú)立的作用域。而正巧合的是,返回的這個(gè)函數(shù)體中,還有一個(gè)自由變量max要引用fn作用域下的fn()上下文環(huán)境中的max。因此,這個(gè)max不能被銷毀,銷毀了之后bar函數(shù)中的max就找不到值了。
因此,這里的fn()上下文環(huán)境不能被銷毀,還依然存在與執(zhí)行上下文棧中。
執(zhí)行到第18行時(shí)
全局上下文環(huán)境將變?yōu)榛顒?dòng)狀態(tài),但是fn()上下文環(huán)境依然會(huì)在執(zhí)行上下文棧中。另外,執(zhí)行完第18行,全局上下文環(huán)境中的max被賦值為100。如下圖:
執(zhí)行到第20行,執(zhí)行f1(15),即執(zhí)行bar(15),創(chuàng)建bar(15)上下文環(huán)境,并將其設(shè)置為活動(dòng)狀態(tài)
創(chuàng)建bar函數(shù)是在執(zhí)行fn()時(shí)創(chuàng)建的。fn()早就執(zhí)行結(jié)束了,但是fn()執(zhí)行上下文環(huán)境還存在與棧中,因此bar(15)時(shí),max可以查找到。如果fn()上下文環(huán)境銷毀了,那么max就找不到了
執(zhí)行完20行就是上下文環(huán)境的銷毀過程
11.8 閉包面試解析實(shí)例按道理,調(diào)用fn1()之后,就會(huì)銷毀fn1()
但是此時(shí)的result為 function(){console.log(n)},(result為fn1()的返回值)
如果要調(diào)用result(),但是result里面的n是自由變量(函數(shù)的特別之處在于可以創(chuàng)建一個(gè)獨(dú)立的作用域,result函數(shù)體內(nèi)沒有定義n,要到他的上層作用域找),
在result的上層作用域fn1()里找到了n
因此result依賴fn1()中的n,所以fn1()在調(diào)用后,并不能銷毀,fn1()中的n一直存在
function fn1() { var n = 0; return function() { console.log(n) } } var result = fn1(); result()11.9 參考
http://www.cnblogs.com/wangfu...
https://zhuanlan.zhihu.com/p/...
http://www.ruanyifeng.com/blo...
用new Object() 的方式新建了一個(gè)對象 obj
取出第一個(gè)參數(shù),就是我們要傳入的構(gòu)造函數(shù)。(此外因?yàn)?shift 會(huì)修改原數(shù)組,所以 arguments 會(huì)被去除第一個(gè)參數(shù))
將 obj 的原型指向構(gòu)造函數(shù),這樣 obj 就可以訪問到構(gòu)造函數(shù)原型中的屬性
使用 apply,改變構(gòu)造函數(shù) this 的指向到新建的對象,這樣 obj 就可以訪問到構(gòu)造函數(shù)中的屬性
返回 obj,(判斷返回的值是不是一個(gè)對象,如果是一個(gè)對象,我們就返回這個(gè)對象,如果沒有,我們該返回什么就返回什么)
12.2 實(shí)例function Person(name, age) { this.name = name; this.age = age; this.call = function() { alert(this.name + this.age) } } var p1 = new Person("jie", 12) p1.call()
function myNew3() { let obj = new Object(); //1 let Constructor = [].shift.call(arguments); //2 obj.__proto__ = Constructor.prototype; //3 let result = Constructor.apply(obj, arguments); //4 if (result instanceof Object) { //5 return result } else { return obj; } } var p4 = myNew3(Person, "wei", 14) p4.call()12.3 參考
https://github.com/mqyqingfen...
13.call 13.1 定義通俗的理解為借用(一個(gè)對象沒有這個(gè)方法,但是別的對象有,不想重復(fù)代碼,所以借來用一下)
call() 方法在使用一個(gè)指定的 this 值和若干個(gè)指定的參數(shù)值的前提下調(diào)用某個(gè)函數(shù)或方法。
13.2 實(shí)例var obj = { value: "1" } function fn(name, age) { this.name = name; this.age = age; this.say = function() { alert(this.name + this.age) } } fn.call(obj, "jie", 10) obj.say()13.3 call的模擬實(shí)現(xiàn)
將函數(shù)設(shè)為對象的屬性
執(zhí)行該函數(shù)
刪除該函數(shù)
Function.prototype.call2 = function(context) { var context = context || window; context.fn = this; var args = []; for (var i = 1; i < arguments.length; i++) { args.push(`arguments[${i}]`) } var result = eval(`context.fn(${args})`) delete context.fn; return result; } fn.call2(obj, "biao", 20) obj.say()13.4 參考
https://www.cnblogs.com/moqiu...
https://github.com/mqyqingfen...
apply與call類型,只是傳參不一樣
14.1 apply的模擬實(shí)現(xiàn)var obj = { value: "1" } function fn(name, age) { this.name = name; this.age = age; this.say = function() { alert(this.name + this.age) } } Function.prototype.apply2 = function(context, arr) { var context = Object(context) || window; context.fn = this; var result; if (!arr) { result = context.fn() } else { var args = []; for (var i = 0; i < arr.length; i++) { args.push(`arr[${i}]`) } result = eval(`context.fn(${args})`) } delete context.fn; return result; } fn.apply(obj, ["jie", 10]) obj.say() fn.apply2(obj, ["biao", 20]) obj.say()15. bind
var foo = { value: 1 }; function bar() { console.log(this.value); } // 返回了一個(gè)函數(shù) var bindFoo = bar.bind(foo); bindFoo(); // 116. arguments
是一個(gè)對應(yīng)于傳遞給函數(shù)的參數(shù)的類數(shù)組對象。
function foo(name, age, sex) { console.log(arguments) } foo("name", "age", "sex")
function fn(...arguments) { console.log(arguments) } fn(1, 2, 3)17 繼承 17.1組合繼承
function Person() { this.name = "jie" this.color = ["red", "blue"] } Person.prototype.say = function() { console.log(this.name) } function Student(id) { Person.call(this) this.id = id } Student.prototype = new Person() Student.prototype.constructor = Student var s1 = new Student("1") console.log(s1.name) console.log(s1.color) s1.say() s1.color.push("yellow") console.log(s1.color) var s2 = new Student("2") console.log(s2.name) console.log(s2.color) s2.say() s2.color.push("white") console.log(s2.color)
https://www.cnblogs.com/sarah...
18 異步 18.1 單線程 18.1.1 什么是單線程Javascript語言的執(zhí)行環(huán)境是"單線程"(single thread)
所謂"單線程",就是指一次只能完成一件任務(wù)。如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再執(zhí)行后面一個(gè)任務(wù),以此類推。
單線程的優(yōu)點(diǎn)
這種模式的好處是實(shí)現(xiàn)起來比較簡單,執(zhí)行環(huán)境相對單純
單線程的缺點(diǎn)
壞處是只要有一個(gè)任務(wù)耗時(shí)很長,后面的任務(wù)都必須排隊(duì)等著,會(huì)拖延整個(gè)程序的執(zhí)行。常見的瀏覽器無響應(yīng)(假死),往往就是因?yàn)槟骋欢蜫avascript代碼長時(shí)間運(yùn)行(比如死循環(huán)),導(dǎo)致整個(gè)頁面卡在這個(gè)地方,其他任務(wù)無法執(zhí)行。
解決單線程的缺點(diǎn)
為了解決這個(gè)問題,Javascript語言將任務(wù)的執(zhí)行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。
同步模式
后一個(gè)任務(wù)等待前一個(gè)任務(wù)結(jié)束,然后再執(zhí)行,程序的執(zhí)行順序與任務(wù)的排列順序是一致的、同步的
異步模式
每一個(gè)任務(wù)有一個(gè)或多個(gè)回調(diào)函數(shù)(callback),前一個(gè)任務(wù)結(jié)束后,不是執(zhí)行后一個(gè)任務(wù),而是執(zhí)行回調(diào)函數(shù),后一個(gè)任務(wù)則是不等前一個(gè)任務(wù)結(jié)束就執(zhí)行,所以程序的執(zhí)行順序與任務(wù)的排列順序是不一致的、異步的。
異步模式的情景
http請求
$.ajax({ url: "", success: function(data) { console.log(data) }, error: function(error) { console.log(error) } })18 異步 18.1 單線程 18.1.1 什么是單線程
Javascript語言的執(zhí)行環(huán)境是"單線程"(single thread)
所謂"單線程",就是指一次只能完成一件任務(wù)。如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再執(zhí)行后面一個(gè)任務(wù),以此類推。
單線程的優(yōu)點(diǎn)
這種模式的好處是實(shí)現(xiàn)起來比較簡單,執(zhí)行環(huán)境相對單純
單線程的缺點(diǎn)
壞處是只要有一個(gè)任務(wù)耗時(shí)很長,后面的任務(wù)都必須排隊(duì)等著,會(huì)拖延整個(gè)程序的執(zhí)行。常見的瀏覽器無響應(yīng)(假死),往往就是因?yàn)槟骋欢蜫avascript代碼長時(shí)間運(yùn)行(比如死循環(huán)),導(dǎo)致整個(gè)頁面卡在這個(gè)地方,其他任務(wù)無法執(zhí)行。
解決單線程的缺點(diǎn)
為了解決這個(gè)問題,Javascript語言將任務(wù)的執(zhí)行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。
同步模式
后一個(gè)任務(wù)等待前一個(gè)任務(wù)結(jié)束,然后再執(zhí)行,程序的執(zhí)行順序與任務(wù)的排列順序是一致的、同步的
異步模式
每一個(gè)任務(wù)有一個(gè)或多個(gè)回調(diào)函數(shù)(callback),前一個(gè)任務(wù)結(jié)束后,不是執(zhí)行后一個(gè)任務(wù),而是執(zhí)行回調(diào)函數(shù),后一個(gè)任務(wù)則是不等前一個(gè)任務(wù)結(jié)束就執(zhí)行,所以程序的執(zhí)行順序與任務(wù)的排列順序是不一致的、異步的。
18.1.2常見的異步操作網(wǎng)絡(luò)請求,如ajax http.get
IO 操作,如readFile readdir
定時(shí)函數(shù),如setTimeout setInterval
18.2 回調(diào)函數(shù)(Callback)// 1秒后打印出aa
function fn1(callback) { setTimeout(function() { callback(); }, 1000) } fn1(fn2) function fn2() { console.log("aa") }18.3 回調(diào)地獄
ajax(url, () => { // 處理邏輯 ajax(url1, () => { // 處理邏輯 ajax(url2, () => { // 處理邏輯 }) }) })18.3.1 callback封裝
function ajaxFn(url, callback) { $.ajax({ method: "get", url: url, success: function(data) { callback(data) }, error: function(error) { console.log(error) } }) } ajaxFn("https://cnodejs.org/api/v1/topic/5433d5e4e737cbe96dcef312", (res) => { console.log(res) console.log("第一個(gè)請求完成") ajaxFn("https://cnodejs.org/api/v1/topics", (ress) => { console.log(ress) console.log("第二個(gè)請求完成") }) })18.3.2 promise封裝
function promiseFn(url) { return new Promise((resolve, reject) => { $.ajax({ method: "get", url: url, success: function(data) { resolve(data) }, error: function(error) { reject(error) } }) }) } promiseFn("https://cnodejs.org/api/v1/topic/5433d5e4e737cbe96dcef312") .then(res => { console.log(res) console.log("第一個(gè)請求完成") return promiseFn("https://cnodejs.org/api/v1/topics") }) .then(res => { console.log(res) console.log("第二個(gè)請求完成") }) .catch(err => { console.log(err) })18.3.3 async/await封裝
async function asyncFn(url) { return await new Promise((resolve, reject) => { $.ajax({ method: "get", url: url, success: function(response) { resolve(response); }, error: function(error) { reject(error); } }) }) } async function start() { var result1 = await asyncFn("https://cnodejs.org/api/v1/topic/5433d5e4e737cbe96dcef312"); var result2 = await asyncFn("https://cnodejs.org/api/v1/topics"); console.log(result1) console.log("第一個(gè)請求完成") console.log(result2) console.log("第二個(gè)請求完成") } start()18.4 阻塞、非阻塞、同步、異步 18.4.1 生活中實(shí)例解析(熱水壺?zé)?
在很久之前,科技還沒有這么發(fā)達(dá)的時(shí)候,如果我們要燒水,需要把水壺放到火爐上,我們通過觀察水壺內(nèi)的水的沸騰程度來判斷水有沒有燒開
隨著科技的發(fā)展,現(xiàn)在市面上的水壺都有了提醒功能,當(dāng)我們把水壺插電之后,水壺水燒開之后會(huì)通過聲音提醒我們水開了。
18.4.2 同步、異步對于燒水這件事兒來說,傳統(tǒng)水壺的燒水就是同步的,高科技水壺的燒水就是異步的
18.4.3 阻塞、非阻塞當(dāng)你把水放到水壺里面,按下開關(guān)后,你可以坐在水壺前面,別的事情什么都不做,一直等著水燒好。你還可以先去客廳看電視,等著水開就好了。
對于你來說,坐在水壺前面等就是阻塞的,去客廳看電視等著水開就是非阻塞的。
18.4.4 阻塞、非阻塞和同步、異步的區(qū)別阻塞、非阻塞說的是調(diào)用者(使用水壺的我),同步、異步說的是被調(diào)用者(水壺)。
19. 深淺拷貝 19.1 js 數(shù)據(jù)類型說起基本數(shù)據(jù)類型保存在棧內(nèi)存,
引用類型保存在堆內(nèi)存中
19.1.1 棧內(nèi)存,堆內(nèi)存var a = 1;//定義了一個(gè)number類型 var obj1 = {//定義了一個(gè)object類型 name:"obj" };19.1.2 基本類型的復(fù)制
var a = 1; var b = a; console.log(a) //1 console.log(b) //1 b = 2; console.log(a) //1 console.log(b) //2
賦值的時(shí)候,在棧內(nèi)存中重新開辟內(nèi)存,存放變量b,所以在棧內(nèi)存中分別存放著變量a、b各自的值,修改時(shí)互不影響
19.1.3 引用類型的復(fù)制var color1 = ["red", "blue"] var color2 = color1; console.log(color1) //["red", "blue"] console.log(color2) //["red", "blue"] color1.push("black"); color1.push("yellow"); console.log(color1) // ["red", "blue", "black", "yellow"] console.log(color2) //["red", "blue", "black", "yellow"]
color1與color2指向堆內(nèi)存中同一地址的同一對象,復(fù)制的只是引用地址
因此,對于引用類型的復(fù)制,簡單賦值無用,需要拷貝。拷貝存在兩種類型:深拷貝與淺拷貝
19.2 淺拷貝淺拷貝只復(fù)制指向某個(gè)對象的指針,而不復(fù)制對象本身,新舊對象還是共享同一塊內(nèi)存
修改新對象會(huì)改到原對象
var person = { p1: { name: "jie", age: 18 }, p2: "biao" } var person1 = person; person1.p1.name = "nine"; console.log(person) //nine console.log(person1) //nine19.3 深拷貝
深拷貝會(huì)另外創(chuàng)造一個(gè)一模一樣的對象,新對象跟原對象不共享內(nèi)存,修改新對象不會(huì)改到原對象
修改新對象不會(huì)改到原對象
function depClone(obj) { var result = JSON.parse(JSON.stringify(obj)); return result; } var person = { p1: { name: "jie", age: 18 }, p2: "biao" } var person2 = depClone(person); person2.p1.name = "nine"; console.log(person) //jie console.log(person2) //nine19.4 參考
https://www.cnblogs.com/136as...
https://github.com/mqyqingfen...
20.2.2 onclick="fn"要不要加()
沒有()
button type="button" onclick="fn" id="btn">點(diǎn)我試試
不彈出框(沒有執(zhí)行alert())
有()
button type="button" onclick="fn" id="btn">點(diǎn)我試試
彈出框(執(zhí)行alert())
第一個(gè)參數(shù)是監(jiān)聽動(dòng)作
第二個(gè)參數(shù)監(jiān)聽事件
第三個(gè)參數(shù)false冒泡,true捕獲
20.4 DOM3級事件
DOM3級事件在DOM2級事件的基礎(chǔ)上添加了更多的事件類型
UI事件,當(dāng)用戶與頁面上的元素交互時(shí)觸發(fā),如:load、scroll
焦點(diǎn)事件,當(dāng)元素獲得或失去焦點(diǎn)時(shí)觸發(fā),如:blur、focus
鼠標(biāo)事件,當(dāng)用戶通過鼠標(biāo)在頁面執(zhí)行操作時(shí)觸發(fā)如:dbclick、mouseup
滾輪事件,當(dāng)使用鼠標(biāo)滾輪或類似設(shè)備時(shí)觸發(fā),如:mousewheel
文本事件,當(dāng)在文檔中輸入文本時(shí)觸發(fā),如:textInput
鍵盤事件,當(dāng)用戶通過鍵盤在頁面上執(zhí)行操作時(shí)觸發(fā),如:keydown、keypress
合成事件,當(dāng)為IME(輸入法編輯器)輸入字符時(shí)觸發(fā),如:compositionstart
變動(dòng)事件,當(dāng)?shù)讓覦OM結(jié)構(gòu)發(fā)生變化時(shí)觸發(fā),如:DOMsubtreeModified
20.4 DOM事件流 20.4.1 為什么是有事件流?假如在一個(gè)button上注冊了一個(gè)click事件,又在其它父元素div上注冊了一個(gè)click事件,那么當(dāng)我們點(diǎn)擊button,是先觸發(fā)父元素上的事件,還是button上的事件呢,這就需要一種約定去規(guī)范事件的執(zhí)行順序,就是事件執(zhí)行的流程。
瀏覽器在發(fā)展的過程中出現(xiàn)了兩種不同的規(guī)范
9以下的IE瀏覽器使用的是事件冒泡,先從具體的接收元素,然后逐步向上傳播到不具體的元素。
Netscapte采用的是事件捕獲,先由不具體的元素接收事件,最具體的節(jié)點(diǎn)最后才接收到事件。
而W3C制定的Web標(biāo)準(zhǔn)中,是同時(shí)采用了兩種方案,事件捕獲和事件冒泡都可以。
20.5 DOM事件模型 20.5.1 什么是DOM事件模型DOM事件模型分為捕獲和冒泡。一個(gè)事件發(fā)生后,會(huì)在子元素和父元素之間傳播(propagation)。這種傳播分成三個(gè)階段。
捕獲階段:事件從window對象自上而下向目標(biāo)節(jié)點(diǎn)傳播的階段;
目標(biāo)階段:真正的目標(biāo)節(jié)點(diǎn)正在處理事件的階段;
冒泡階段:事件從目標(biāo)節(jié)點(diǎn)自下而上向window對象傳播的階段。
20.5.2 事件捕獲捕獲是從上到下,事件先從window對象,然后再到document(對象),然后是html標(biāo)簽(通過document.documentElement獲取html標(biāo)簽),然后是body標(biāo)簽(通過document.body獲取body標(biāo)簽),然后按照普通的html結(jié)構(gòu)一層一層往下傳,最后到達(dá)目標(biāo)元素。我們只需要將addEventListener的第三個(gè)參數(shù)改為true就可以實(shí)現(xiàn)事件捕獲
Document 爺爺父親兒子
點(diǎn)擊id為child1的div標(biāo)簽時(shí)(兒子框),打印的結(jié)果是爺爺 => 爸爸 => 兒子,。
20.5.2 事件冒泡Document 爺爺父親兒子
點(diǎn)擊id為child1的div標(biāo)簽時(shí)(兒子框),打印的結(jié)果是兒子=>爸爸=>爺爺
20.6 事件代理(事件委托) 20.6.1 事件代理含義和為什么要優(yōu)化?由于事件會(huì)在冒泡階段向上傳播到父節(jié)點(diǎn),因此可以把子節(jié)點(diǎn)的監(jiān)聽函數(shù)定義在父節(jié)點(diǎn)上,由父節(jié)點(diǎn)的監(jiān)聽函數(shù)統(tǒng)一處理多個(gè)子元素的事件。這種方法叫做事件的代理(delegation)。
舉個(gè)例子,比如一個(gè)宿舍的同學(xué)同時(shí)快遞到了,一種方法就是他們都傻傻地一個(gè)個(gè)去領(lǐng)取,還有一種方法就是把這件事情委托給宿舍長,讓一個(gè)人出去拿好所有快遞,然后再根據(jù)收件人一一分發(fā)給每個(gè)宿舍同學(xué);
在這里,取快遞就是一個(gè)事件,每個(gè)同學(xué)指的是需要響應(yīng)事件的 DOM 元素,而出去統(tǒng)一領(lǐng)取快遞的宿舍長就是代理的元素,所以真正綁定事件的是這個(gè)元素,按照收件人分發(fā)快遞的過程就是在事件執(zhí)行中,需要判斷當(dāng)前響應(yīng)的事件應(yīng)該匹配到被代理元素中的哪一個(gè)或者哪幾個(gè)。
那么利用事件冒泡或捕獲的機(jī)制,我們可以對事件綁定做一些優(yōu)化。 在JS中,如果我們注冊的事件越來越多,頁面的性能就越來越差,因?yàn)椋?/p>
函數(shù)是對象,會(huì)占用內(nèi)存,內(nèi)存中的對象越多,瀏覽器性能越差
注冊的事件一般都會(huì)指定DOM元素,事件越多,導(dǎo)致DOM元素訪問次數(shù)越多,會(huì)延遲頁面交互就緒時(shí)間。
刪除子元素的時(shí)候不用考慮刪除綁定事件
20.6.2 優(yōu)點(diǎn)
減少內(nèi)存消耗,提高性能
如果給每個(gè)列表項(xiàng)一一都綁定一個(gè)函數(shù),那對于內(nèi)存消耗是非常大的,效率上需要消耗很多性能。借助事件代理,我們只需要給父容器ul綁定方法即可,這樣不管點(diǎn)擊的是哪一個(gè)后代元素,都會(huì)根據(jù)冒泡傳播的傳遞機(jī)制,把容器的click行為觸發(fā),然后把對應(yīng)的方法執(zhí)行,根據(jù)事件源,我們可以知道點(diǎn)擊的是誰,從而完成不同的事。
動(dòng)態(tài)綁定事件
在很多時(shí)候,我們需要通過用戶操作動(dòng)態(tài)的增刪列表項(xiàng)元素,如果一開始給每個(gè)子元素綁定事件,那么在列表發(fā)生變化時(shí),就需要重新給新增的元素綁定事件,給即將刪去的元素解綁事件,如果用事件代理就會(huì)省去很多這樣麻煩。
這是常規(guī)的實(shí)現(xiàn)事件委托的方法,但是這種方法有BUG,當(dāng)監(jiān)聽的元素里存在子元素時(shí),那么我們點(diǎn)擊這個(gè)子元素事件會(huì)失效,所以我們可以聯(lián)系文章上一小節(jié)說到的冒泡事件傳播機(jī)制來解決這個(gè)bug。改進(jìn)的事件委托代碼:
preventDefault阻止默認(rèn)行為
如果調(diào)用這個(gè)方法,默認(rèn)事件行為將不再觸發(fā)。什么是默認(rèn)事件呢?例如表單一點(diǎn)擊提交按鈕(submit)刷新頁面、a標(biāo)簽?zāi)J(rèn)頁面跳轉(zhuǎn)或是錨點(diǎn)定位等。
a標(biāo)簽?zāi)J(rèn)頁面跳轉(zhuǎn)
鏈接
輸入框最多只能輸入六個(gè)字符
20.7.2 event.stopPropagation()
stopPropagation停止冒泡
event.stopPropagation() 方法阻止事件冒泡到父元素,阻止任何父事件處理程序被執(zhí)行
爺爺父親兒子
只打印console.log("btn click 1");
爺爺父親兒子
點(diǎn)擊兒子的時(shí)候,打印兒子,爸爸
點(diǎn)擊爸爸的時(shí)候,打印爸爸
https://juejin.im/post/5c71e8...
https://github.com/ljianshu/B...
function random() { var arr = [] for (var i = 0; i < 100; i++) { //生成循環(huán)100次,生成100個(gè)數(shù)字。該方法最大的弊端,為了避免有重復(fù)的情況導(dǎo)致數(shù)組不足10個(gè)元素,所以生成較多的數(shù)字 var num = Math.floor(Math.random() * 100) //生成0-100的隨機(jī)整數(shù) if (arr.length == 0) { arr.push(num) //數(shù)組為空時(shí)直接放入數(shù)組 } else { for (var j = 0; j < arr.length; j++) { //循環(huán)已存在的數(shù)組 if (arr.join(",").indexOf(num) < 0 && arr.length < 10) { //判斷已存在數(shù)組中是否已有剛生成的數(shù)字,如沒有且數(shù)組長度不足10才將num放入arr arr.push(num) //這樣又會(huì)導(dǎo)致生成的大部分?jǐn)?shù)字被arr.length <= 10排除掉了,浪費(fèi)性能 } } } } return arr }
let set = new Set() while (set.size < 10) { //多少 set.add(Math.round(Math.random() * 10) + 0) //最大值,最小值 } let arr4 = Array.from(set) console.log(arr4)
var arr5 = new Array() while (arr5.length < 10) { var num = Math.round(180 * Math.random()) + 20 var exists = false for (var i = 0, l = arr5.length; i < l; i++) { if (arr5[i] == num) { //判斷是否已經(jīng)存在 exists = true //存在的話將true傳給exists } } if (!exists) { //現(xiàn)在exist是true,!exists就是false,所以不執(zhí)行這個(gè)if下面代碼。 arr5.push(num) } } console.log(arr5)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/103974.html
摘要:收集的一些前端面試題從面試題發(fā)現(xiàn)不足,進(jìn)而查漏補(bǔ)缺,比通過面試更難得及各大互聯(lián)網(wǎng)公司前端筆試面試題篇及各大互聯(lián)網(wǎng)公司前端筆試面試題篇面試題個(gè)和個(gè)經(jīng)典面試題前端開發(fā)面試題如何面試前端工程師很重要個(gè)變態(tài)題解析如何通過餓了么面試輕 收集的一些前端面試題 從面試題發(fā)現(xiàn)不足,進(jìn)而查漏補(bǔ)缺,比通過面試更難得 1 BAT及各大互聯(lián)網(wǎng)公司2014前端筆試面試題--Html,Css篇 2 BAT...
摘要:收集的一些前端面試題從面試題發(fā)現(xiàn)不足,進(jìn)而查漏補(bǔ)缺,比通過面試更難得及各大互聯(lián)網(wǎng)公司前端筆試面試題篇及各大互聯(lián)網(wǎng)公司前端筆試面試題篇面試題個(gè)和個(gè)經(jīng)典面試題前端開發(fā)面試題如何面試前端工程師很重要個(gè)變態(tài)題解析如何通過餓了么面試輕 收集的一些前端面試題 從面試題發(fā)現(xiàn)不足,進(jìn)而查漏補(bǔ)缺,比通過面試更難得 1 BAT及各大互聯(lián)網(wǎng)公司2014前端筆試面試題--Html,Css篇 2 BAT...
摘要:特意對前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...
摘要:函數(shù)式編程前端掘金引言面向?qū)ο缶幊桃恢币詠矶际侵械闹鲗?dǎo)范式。函數(shù)式編程是一種強(qiáng)調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。 JavaScript 函數(shù)式編程 - 前端 - 掘金引言 面向?qū)ο缶幊桃恢币詠矶际荍avaScript中的主導(dǎo)范式。JavaScript作為一門多范式編程語言,然而,近幾年,函數(shù)式編程越來越多得受到開發(fā)者的青睞。函數(shù)式編程是一種強(qiáng)調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。因此,...
摘要:詳解十大常用設(shè)計(jì)模式力薦深度好文深入理解大設(shè)計(jì)模式收集各種疑難雜癥的問題集錦關(guān)于,工作和學(xué)習(xí)過程中遇到過許多問題,也解答過許多別人的問題。介紹了的內(nèi)存管理。 延遲加載 (Lazyload) 三種實(shí)現(xiàn)方式 延遲加載也稱為惰性加載,即在長網(wǎng)頁中延遲加載圖像。用戶滾動(dòng)到它們之前,視口外的圖像不會(huì)加載。本文詳細(xì)介紹了三種延遲加載的實(shí)現(xiàn)方式。 詳解 Javascript十大常用設(shè)計(jì)模式 力薦~ ...
摘要:手冊網(wǎng)超級有用的前端基礎(chǔ)技術(shù)面試問題收集前端面試題目及答案匯總史上最全前端面試題含答案常見前端面試題及答案經(jīng)典面試題及答案精選總結(jié)前端面試過程中最容易出現(xiàn)的問題前端面試題整理騰訊前端面試經(jīng)驗(yàn)前端基礎(chǔ)面試題部分最新前端面試題攻略前端面試前端入 手冊網(wǎng):http://www.shouce.ren/post/index 超級有用的前端基礎(chǔ)技術(shù)面試問題收集:http://www.codec...
閱讀 2753·2021-11-22 14:45
閱讀 896·2021-10-15 09:41
閱讀 1058·2021-09-27 13:35
閱讀 3662·2021-09-09 11:56
閱讀 2626·2019-08-30 13:03
閱讀 3191·2019-08-29 16:32
閱讀 3296·2019-08-26 13:49
閱讀 766·2019-08-26 10:35