JS
延遲加載js
<script src="" defer> </script>
<script src="" async> </script>
defer 異步并行下載穿扳,在document解析完后執(zhí)行,多腳本按順序執(zhí)行国旷,
async 異步并行下載矛物,只要下載完就執(zhí)行,不分順序跪但。
輸出結(jié)果
console.log(typeof NaN)
console.log(typeof undefined)
console.log(typeof null)
number , undefined obj
null 是特殊的object 類型
輸出結(jié)果
console.log(true + 1)
console.log('jason' + true)
console.log(undefined + 1)
2 , jasontrue , NaN
基本上處理字符串優(yōu)先轉(zhuǎn)化履羞,剩下的都是Number轉(zhuǎn)化,
Number(true) = 1
Number(undefined) 結(jié)果為NaN ,NaN+什么數(shù)字都是NaN
輸出結(jié)果
var bar = 1
function test() {
console.log(bar)
var bar = 2;
console.log(bar);
}
undefined 屡久, 2
在test方法里吧雹,定義的var bar = 2 被變量提升了。
輸出結(jié)果
for(var i= 0; i<3; i++) {
setTimeout(function () {
console.log(i)
},1000)
}
3,3,3 間隔為1秒
因為訪問的是for 里定義的var i 所有定時起
輸出結(jié)果
var foo = function() {
console.log(1)
}
function foo() {
console.log(2)
}
foo()
1
聲明的優(yōu)先
輸出結(jié)果
function c() {
var b = 1;
function a() {
console.log(b)
var b = 2
console.log(b)
}
console.log(b)
}
c()
undefined , 2 ,1
輸出結(jié)果
var name = 'aaa'
(function(){
if(typeof name == 'undefined') {
var name = 'java'
consolo.log("111",name)
}else {
consolo.log("222",name)
}
})()
輸出:111java
匿名函數(shù)是一個塊作用域的模擬涂身,if沒有作用域雄卷,但是下面有定義了var,所以變量只能提升到匿名函數(shù)內(nèi)蛤售,name為undefined
輸出結(jié)果
var f = true
if( f === true) {
var a = 10;
}
function fn() {
var b = 20;
c = 30;
}
fn()
console.log(a)
console.log(c)
console.log(b)
10, 20,報錯
var 沒有塊概念丁鹉,所以a全局能拿到,
c是直接綁定在window上悴能,所以也能拿到
b由于是定義在方法揣钦,外部無法找到,直接找不到定義漠酿,報錯
輸出結(jié)果
var a = {}
var b = { key : 'a'}
var c = {key:'c'}
a[b] = '111'
a[c] = '222'
console.log(a[b])
222
注意這里的a[b]里面的b 對象會被轉(zhuǎn)化成字符串'[object Object]' 冯凹。
同理 a[c] 里的c 也會被轉(zhuǎn)化成 '[object Object]'
所以 結(jié)果是 a['[object Object]'] = '111' ; a['[object Object]'] = '222'
所有最后等于222
js數(shù)組去除重復(fù)的方法
//方法1 new Set
function unique(array) {
let set = new Set(array)
return Array.form(set)
}
//方法2 遍歷 indexOf
function unique(array) {
let lastList = []
array.foreach( (item) => {
if(lastList.indexOf(item) < 0) {
lastList.push(item)
}
})
return lastList
}
//方法3 遞歸刪除法
function unique(array) {
array = array.sort()
var len = array.length
function loop(index) {
if(index >= 1) {
if(array[index] === array[index - 1 ]) {
array.splice(index,1)
}
loop(index - 1)
}
}
loop(len - 1)
return array
}
console.log(unique2([3,4,4,1,2,4,1,100,3]))
//方法4 兩數(shù)組對比法
function unique3(array) {
array = array.sort()
let lastList = [array[0]] //初始化 就保存第一元素 然后逐一跟數(shù)組對比,有重復(fù)
for(var i = 0; i < array.length; i++) {
if(lastList[lastList.length - 1] !== array[i]) {//如果當(dāng)前l(fā)ast里面沒有則加入
lastList.push(array[i])
}
}
return lastList
}
console.log(unique3([3,4,4,1,2,4,1,100,3]))
給字符串添加addPre方法炒嘲,實現(xiàn) "job".addPre("good") 輸出 good job
通過原型鏈的方法實現(xiàn)
String.prototype.addPre = function(str) {
return str + this
}
把嵌套的二維數(shù)組轉(zhuǎn)化成一維數(shù)組
let a =
[
[4,5,6,7],
[7,8,9],
[1,2,3],
]
輸出
[4,5,6,7,7,8,9,1,2,3]
//方法1
function arr2ToArr(arr) {
let newList = []
arr.forEach(item => {
newList = newList.concat(item)
})
return newList
}
console.log(arr2ToArr(a))
把嵌套的二維數(shù)組 里面最大的取出宇姚,組成新數(shù)組
let a =
[
[4,5,6,7],
[7,8,9],
[1,2,3],
]
輸出
[7,9夫凸,3]
function arr2ToMaxArr(arr) {
let newList = []
arr.forEach(item => {
newList = newList.push(Math.max.apply(null,item)) //這里apply可以解構(gòu)數(shù)組為動態(tài)參數(shù)
})
return newList
}
console.log(arr2ToMaxArr(a))
閉包
定義:一個函數(shù)可以調(diào)用另外一個函數(shù)的作用域中的變量
函數(shù)內(nèi)還有函數(shù)浑劳,兩個函數(shù)作用域相連,形成閉包
形成條件:函數(shù)嵌套夭拌,內(nèi)部函數(shù)調(diào)用外部函數(shù)變量
for(var i= 0; i<3; i++) {
(function (i){
setTimeout(function () {
console.log(i)
},1000)
})(i)
}
能夠正常輸出 1魔熏,2,3 間隔1秒鸽扁,因為形成閉包蒜绽,i 變量被保留下來。
call apply bind區(qū)別
三個都是改變執(zhí)行的上下文對象桶现,可以實現(xiàn)繼承
call和apply都是立即調(diào)用
call(obj,parm1躲雅,parm2) 第二個參數(shù)可以是 動態(tài)參數(shù),適合解構(gòu)
apply(obj,arr) 第二個參數(shù)必須是數(shù)組
bind 和call使用類似巩那,只提前綁定吏夯,返回新函數(shù),但不立即調(diào)用方法即横。
js判斷變量是否為數(shù)組
//
var arr = []
arr instanceof Array
// true
var arr = []
Object.prototype.toString.call(arr)
//"[object Array]"
var arr = []
Array.prototype.isPrototypeOf(arr)
//true
var arr = []
arr.constructor.toString()
//"function Array() { [native code] }"
var arr = []
Array.isArray(arr)
//true
new操作做了什么事情
- 創(chuàng)建一個空對象
- 將this 指向這個對象
- 通過this給對象添加屬性
- 通過this噪生,將proto屬性指向構(gòu)造函數(shù)的原型對象
/*
create函數(shù)要接受不定量的參數(shù),第一個參數(shù)是構(gòu)造函數(shù)(也就是new操作符的目標(biāo)函數(shù))东囚,其余參數(shù)被構(gòu)造函數(shù)使用跺嗽。
new Create() 是一種js語法糖。我們可以用函數(shù)調(diào)用的方式模擬實現(xiàn)
*/
function create(Con,...args){
//1页藻、創(chuàng)建一個空的對象
let obj = {}; // let obj = Object.create({});
//2桨嫁、將空對象的原型prototype指向構(gòu)造函數(shù)的原型
Object.setPrototypeOf(obj,Con.prototype); // obj.__proto__ = Con.prototype
//3、改變構(gòu)造函數(shù)的上下文(this),并將剩余的參數(shù)傳入
let result = Con.apply(obj,args);
//4份帐、在構(gòu)造函數(shù)有返回值的情況進(jìn)行判斷
return result instanceof Object?result:obj;
}
①proto和constructor屬性是對象所獨有的璃吧;
② prototype屬性是函數(shù)所獨有的。但是由于JS中函數(shù)也是一種對象废境,所以函數(shù)也擁有proto和constructor屬性畜挨。
proto屬性都是由一個對象指向一個對象,即指向它們的原型對象(也可以理解為父對象)噩凹,
它的作用就是當(dāng)訪問一個對象的屬性時巴元,如果該對象內(nèi)部不存在這個屬性,那么就會去它的proto屬性所指向的那個對象(可以理解為父對象)里找驮宴,如果父對象也不存在這個屬性逮刨,則繼續(xù)往父對象的proto屬性所指向的那個對象里找,如果還沒找到堵泽,則繼續(xù)往上找…直到原型鏈頂端null修己,再往上找就相當(dāng)于在null上取值,會報錯.
由以上這種通過proto屬性來連接對象直到null的一條鏈即為我們所謂的原型鏈迎罗。
prototype屬性它是函數(shù)所獨有的箩退,它是從一個函數(shù)指向一個對象。它的含義是函數(shù)的原型對象佳谦,
也就是這個函數(shù)(其實所有函數(shù)都可以作為構(gòu)造函數(shù))所創(chuàng)建的實例的原型對象戴涝,
由此可知:f1.proto === Foo.prototype,它們兩個完全一樣钻蔑。
作用:讓該函數(shù)所實例化的對象們都可以找到公用的屬性和方法啥刻。任何函數(shù)在創(chuàng)建的時候,其實會默認(rèn)同時創(chuàng)建該函數(shù)的prototype對象咪笑。
constructor屬性的含義就是指向該對象的構(gòu)造函數(shù)可帽,所有函數(shù)(此時看成對象了)最終的構(gòu)造函數(shù)都指向Function
因為創(chuàng)建對象的前提是需要有constructor,而這個constructor可能是對象自己本身顯式定義的或者通過proto在原型鏈中找到的窗怒。而單從constructor這個屬性來講映跟,只有prototype對象才有蓄拣。每個函數(shù)在創(chuàng)建的時候,JS會同時創(chuàng)建一個該函數(shù)對應(yīng)的prototype對象努隙,而函數(shù)創(chuàng)建的對象.proto === 該函數(shù).prototype球恤,該函數(shù).prototype.constructor===該函數(shù)本身,故通過函數(shù)創(chuàng)建的對象即使自己沒有constructor屬性荸镊,它也能通過proto找到對應(yīng)的constructor咽斧,所以任何對象最終都可以找到其構(gòu)造函數(shù)(null如果當(dāng)成對象的話,將null除外)躬存。
原型鏈
當(dāng)訪問對象屬性時候张惹,會先在對象本身屬性找,沒有則去proto隱式原型找岭洲,即構(gòu)造函數(shù)的prototype 宛逗,沒有繼續(xù)在prototype的proto找,這樣一層層查找形成鏈?zhǔn)健?br> 總結(jié):
- 一直往上找盾剩,直到null都沒有拧额,就返回undefined
- Object.prototype.proto === null
js繼承判斷
- 原型鏈繼承
- 構(gòu)造函數(shù)繼承
- 實例繼承
- 組合繼承
- 寄生組合
- es6 extends
== 和 === 區(qū)別
== 是語法糖,會轉(zhuǎn)化成對應(yīng)的數(shù)據(jù)類型彪腔,再比較侥锦。
=== 是完全匹配
cookie 和 session區(qū)別
cookie 是保留在客戶端,而且容量大小有限制德挣,不安全恭垦,明文可以篡改。
session保留在服務(wù)端格嗅,訪問多了番挺,會響應(yīng)服務(wù)端性能。通過客戶端記錄ID 在cookie 實現(xiàn)用戶登陸態(tài)記錄屯掖。
sort背后的原理
js自帶的排序方法玄柏。
通過 unicode編碼進(jìn)行排序 ,默認(rèn)是從小到大排序
slice和splice區(qū)別
slice 切割數(shù)組贴铜,返回切割后的內(nèi)容粪摘,但原數(shù)組不改變
splice 可以刪除和插入數(shù)據(jù),替換绍坝,并返回刪除的數(shù)據(jù)徘意,原數(shù)組也會變化。
深度拷貝和淺拷貝區(qū)別
淺拷貝: 對于對象轩褐,只是復(fù)制對象的引用椎咧,修改屬性,會導(dǎo)致兩邊修改把介。一般用Object.assign()
深度拷貝:完全復(fù)制對象的每一個屬性勤讽,每一個值蟋座,并且嵌套對象依然是完全拷貝。并且被復(fù)制對象與拷貝對象無關(guān)聯(lián)脚牍。修改不影響向臀。
通過字符串轉(zhuǎn)化再轉(zhuǎn)對象 JSON.stringify JSON.parse可以實現(xiàn)。但是如果拷貝對象包含正則表達(dá)式莫矗,函數(shù),或者undefined等值砂缩,此方法就會出現(xiàn)問題
自己實現(xiàn)遞歸遍歷每一個屬性
ES6
1.var,let,const 區(qū)別
var
- 存在變量提升
- 可以重復(fù)定義同一個var 變量名
- var 在全局定義作谚,會直接添加到window
let
- 不存在變量提升
- 不能重復(fù)定義一樣的變量名
- 不會添加到window
- 存在塊作用域
- 有暫時性死區(qū)
var temp = 0
if(true){
temp = 10
let temp ;//由于這里定義了let 所以在 if塊內(nèi) let上面的代碼都會變成死區(qū)
}
const
和 let 差不多,但是cost不能被修改
看看結(jié)果
function demo(){
let n = 2
if (true) {
let n = 1
}
console.log(n)//以當(dāng)前塊范圍取值
}
demo()
//輸出2
輸出結(jié)果
const demo = (first,...num) => {
return [first,num]
}
demo(1,2,3,4,5)
輸出:[1,[2,3,4,5]]
合并對象方法
Object.assign()
Object.assign(tragetObj,inputObj)
解構(gòu)
let newObj = {...a, ...b}
遍歷屬性賦值
for (var key in souce) {
targetObj[key] = souceObj[key]
}
promise的幾個狀態(tài)
有三個狀態(tài) pending(進(jìn)行中) fulfilled rejected
箭頭函數(shù)和普通函數(shù)區(qū)別
箭頭:
- 是匿名函數(shù)庵芭,不能做構(gòu)造函數(shù)妹懒,不能用new
- 沒有arguments,使用的是rest參數(shù)
rest 參數(shù)(形式為...變量名)双吆,用于獲取函數(shù)的多余參數(shù)
const test = (...arg) => {
console.log(arg[0])
}
test(1,2)
- 不綁定 this 獲取其所在最近上下文的this使用
- 通過call apply 方法調(diào)用函數(shù)眨唬,只需傳一個參數(shù),對this沒有影響
let obj = {
name: "qianzhixiang",
func: (a,b) => {
console.log(this.name,a,b);
}
};
obj.func(1,2); // 1 2
let func = obj.func;
func(1,2); // 1 2
let func_ = func.bind(obj);
func_(1,2);// 1 2
func(1,2);// 1 2
func.call(obj,1,2);// 1 2
func.apply(obj,[1,2]);// 1 2
- 箭頭函數(shù)沒有原型屬性
- 函數(shù)不能做generator函數(shù)好乐,不能使用yied
foreach map filter 區(qū)別
map返回新的數(shù)組對象
foreach和map都是遍歷數(shù)組
filter 返回原數(shù)組的子集合匾竿,通過返回的ture/ false 判斷添加返回的數(shù)組里。