- 亦或
給定一個非空整數數組,除了某個元素只出現一次以外,其余每個元素均出現兩次。找出那個只出現了一次的元素。
亦或:如果a,b兩個值相同則亦或為0,如果不同則亦或為1
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0
3 ^ 3 = 0
for(let i = 1 , len = nums.length;i < len; i ++){
nums[ 0 ] ^ = nums[ i ]
}
return nums[0]
? 結題答案中有用map數組比我用for循環計算時間少,why?
可能是網絡延時!!!!
for循環的性能應該是最好的
- Array: map forEach
map 和forEach都接受兩個參數,第一個參數必填是個函數,第二個參數選填,作用是改變函數中this指向
var name = 'wky'
var a = { name = "yc" }
var b = [1,3,4]
b.map(function(val,index){
return val + this.name
})
// 輸出 ['1wky','3wky','4wky']
b.map(function(val,index){
return val + this.name
},a)
//輸出 [ '1yc', '3yc','4yc' ]
// 注:箭頭函數this指向不變,仍指向父級中this指向
b.map(val =>{ return val + this.a },a)
// 輸出輸出 ['1wky','3wky','4wky']
-
? undefined == null true
0 == undefined false
''== undefined false
0 == null false
'' == null false
詳見末尾寬松相等
- 基礎類型
字符串布爾類型都有方法,是因為使用對應的變量時,編譯器會將其裝箱成對應的對象類型,例如 var s = 'test',如果使用s變量時會將s = new String(s)進行封裝,一旦屬性引用結束,這個新創建的對象就會被銷毀
var s = 'test';
s == new String(s) // true
s.len = 4
s.len // undefined
-
arguments 和 function
1.1 函數形參和實參
在函數體中存在一個形參的引用,指向當前傳入的實參列表,通過它可以獲得參數的值1.2 函數體內this指向
在嚴格模式中this 指向 undefined1.3 arguments
- arguments 是指向實參對象的引用
- arguments中的數組 與形參是別名的關系
- 嚴格模式下 arguments是個保留字,并且不能被重新賦值
- 非嚴格模式下 arguments是個標識符, 能被修改
function test(){ 'use strict'; console.log( arguments ); arguments = 1 } // 報錯 Uncaught SyntaxError: Unexpected eval or arguments in strict mode function test(){ arguments =2; console.log( arguments ); arguments = 1 } // arguments 輸出為2
1.4 閉包
關聯到閉包的作用域鏈都是活動的,嵌套的函數不會講作用域內的私有成員復制一份,也不會對所綁定的變量生成靜態快照。
1.5 函數屬性、方法和構造函數
- 函數length和函數實際參數的length
function check(a, b ,c){ console.log(arguments.length); // 實際參數個數 console.log(arguments.callee.length); // 函數期待參數個數 }
- call 和 apply方法
call 和 apply方法 第一個參數的作用是改變函數體中this的指向,第二個參數是參數,可傳可不傳
var obj = { test: function(){console.log(this.a)}, a: '10' } var a = 20; obj.test.call(null); // 20 obj.test.call(obj); // 10 Object.prototype.toString.call([]) // 改變的是toString中this的指向
apply 參數傳入的是個數組,但是會將數組參數和函數形參一一對應
function testArray(a){ console.log(a) } testArray.apply(null,[1,3]) <!--輸出 1--> function test(a,b){ console.log(a);console.log(b) } test.apply([1,3]) <!--輸出 1, 3-->
當檢測Array實例時, Array.isArray 優于 instanceof,因為Array.isArray能檢測iframes
var iframe = document.createElement('iframe'); document.body.appendChild(iframe); xArray = window.frames[window.frames.length-1].Array; var arr = new xArray(1,2,3); // [1,2,3] // Correctly checking for Array Array.isArray(arr); // true // Considered harmful, because doesn't work though iframes arr instanceof Array; // false
-
第一個參數改變函數內部this指向的函數還有Array類中的方法:
- forEach
- filter
- findIndex
- find
- map
reduce 如果在空數組上調用reduce必須給一個默認值不然就會報錯
const array = []; const reducer = (c, a) => c + a ; array.reduce(reducer) <!--VM1172:1 Uncaught TypeError: Reduce of empty array with no initial value--> <!-- at Array.reduce (<anonymous>)--> <!-- at <anonymous>:1:7--> <!--(anonymous) @ VM1172:1--> array.reduce(reducer,0) <!--0-->
array.length 值是一個無符號32位整數
- bind : 第一個參數改變this指向,第二個是傳入的參數
- 構造函數 Function構造函數創建的函數并不使用詞法作用域,相反,函數體代碼的編譯總是會在頂層函數執行.
function con (){ const local = 'local'; return new Function ('return local'); } const local = 'global'; con()(); // global function con(){ var scope1 = 'local'; return function(){ console.log( scope1 ); } } var scope1 = 'global'; con()(); // 輸出 local
-
promise promise.all await async generator setTimeout
- setTimeout (function,delay,param)
function test(value){ console.log(value) } setTimeout(test,500,10) // 500ms之后 輸出10 // 參數是待執行函數的參數
-
Promise.resolve()
需要將現有對象轉換為Promise對象
- 參數是一個Promise實例
如果參數是一個Promise實例,那么Promise.resolve將不做任何修改、原封不動的返回這個實例 - 參數是一個thenable對象
thenabel對象是指具有then方法的對象,例如:
let thenable = { then:(resolve,reject)=>{ return resolve(21); } }
Promise.resolve()方法將這個對象轉換為Promise對象,并立即執行then方法
let thenable = { then:(resolve,reject)=>{ return resolve(21); } } let p1 = Promise.resolve(thenable)
- 參數不是具有then的對象,或者根本不是對象
返回一個新的promise對象 - 不帶有任何參數
直接返回一個Promise對象
- 參數是一個Promise實例
Promise原理(暫時還是有點懵,可能需要在看看?)
function Promise(fn){ var state = "pending"; var value = null; var callbacks = []; this.then = function(onFulfilled){ return new Promise(function( resolve ){ handle({ onFulfilled: onFulfilled || null, resolve: resolve }); }) }; function handle(callback){ if( state == 'pending' ){ callbacks.push(callback); return ; } if(!callback.onFulfilled){ callback.resolve(value); return; } var ret = callback.onFulfilled(value); callback.resolve(ret); } function resolve(newValue){ if(newValue && (typeof newValue ==='object' || typeof newValue ==='function')){ var then = newValue.then; if(typeof then ==='function'){ then.call(newValue,resolve); return; } } state = 'fulfilled'; value = newValue; setTimeout(function(){ callbacks.forEach(function(callback){ handle(callback); }) },0); } fn(resolve); }
generator 自執行函數
function co(gen){
var g = gen();
var t = g.next();
function next(res){
console.log(res);
if(res.done) return ;
if(typeof g.next !='function') return;
if(res.value instanceof Promise){
res.value.then(value =>{
res = g.next(value);
next(res);
})
}
}
next(t)
};
注意: g.next(value) 這個value對應的值是上一個yield的返回值
-
JSON.stringify 接受三個參數 (value,replace,space)
- replace 是函數
JSON.stringify({name:'name',function(key,value){key // key value // 值 }})
- replace是數組
JSON.stringify({1:1,2:1,3:1,5:1},[1,5]) // "{ "1":1,"5":1 }"
for of 只能遍歷存在 Symbol.iterator接口的數據結構,對象不存在這個接口,所以只能通過手動添加這個遍歷器接口
var Obj = { name:'name',age:18 ,info:{ name:'infoName',age:'infoAge' }};
Object.defineProperty(Obj,Symbol.iterator,{
value:function(){
var o = this;
var idx = 0;
var ks = Object.keys(o);
return {
next:function(){
return {
value: o[ks[idx++]],
done: idx > ks.length
}
}
}
},
enumerabel: false,
writable: false,
configurable: true,
});
for(let value of Obj){
console.log(value);
}
// 輸出 name 18 info:{ name:'infoName', age:'infoAge' }
-
原型 繼承
- Object.create模擬實現
Object.create = function (o){ var F = function(){}; F.prototype = o; return new F(); }
-
強制類型轉換
- JSON.stringify轉換規則(ToString)
- 字符串、數字、布爾值和null的轉換規則和ToString一致
- 如果傳遞給JSON.stringify的對象中定義了toJSON方法,那么該方法會在字符串化前調用,以便將對象轉化成安全的JSON值
var a ={ name:'wky', age:10, toJSON:function(){ return this.name } } JSON.stringify(a) ;// ""wky""
- ToNumber
為了將值轉換為基本數據類型,抽象操作ToPrimitive會先檢查該值是否有valueof()方法,沒有然后在檢查是否有通toString()方法
var a = { valueOf:function(){ return '23' }, toString:function(){ return '12' } } Number(a) // 23
-
寬松相等
- 字符串和數字之間相等的比較
字符串轉換成數字
'42' == 42 // true Number('42') == 42
- 其他類型和Boolean類型的比較
boolean類型轉換成number
'42' == true // false '42' == Number(true)1
- null 與undefined對比 (相等)
- 對象與非對象的比較
ToPrimative(Obj) == 字符串或者數字
42 == [42] // true
如何判斷對象是原生的還是非原生對象
原生對象 執行toString()方法之后函數中會出現'native code'函數