- 亦或
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
亦或:如果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'函数