js题摘录(柯里化、栈队列)

I belong to : Collection


44个Javascript变态题解析

foreach

数组的foreach可以和闭包起一样的作用

闭包中的变量包括参数,在内部函数执行完毕之前不会被释放

JS运行机制

执行栈,任务队列

process.nextTick方法可以在当前"执行栈"的尾部----下一次Event Loop(主线程读取"任务队列")之前----触发回调函数

setImmediate方法则是在当前"任务队列"的尾部添加事件

process.nextTick指定的回调函数是在本次"事件循环"触发,而setImmediate指定的是在下次"事件循环"触发

setTimeout(fn,0)表示当前代码执行完(执行栈清空)以后,立即执行(0毫秒间隔)指定的回调函数。

Promise,里面的函数是直接执行的.

Promise 的 then 应当会放到当前 "执行栈"的尾部

在Javascript引擎里面,队列还分为 Task队列(也有人叫做 MacroTask)和 MicroTask队列, MicroTask会优先于 Task执行。

比如常见的点击事件、 setImmediate、 setTimeout、 MessageChannel等会放入 Task队列,

但是 Promise以及 MutationObserver会放到 Microtask队列。

同时,Javascript引擎在执行 Microtask队列的时候,如果期间又加入了新的 Microtask,则该 Microtask会加入到之前的 Microtask队列的尾部,保证 Microtask先于 Task队列执行。

Task(MacroTask)队列中: setImmediate > MessageChannel > setTimeout 0

你真的了解Javascript执行顺序么?

setTimeOut

谈谈JavaScript的异步实现

你知道为什么会有 Generator 吗?

你知道为什么会有 Generator 吗

柯里化--部分求值

柯里化又称部分求值,柯里化函数会接收一些参数,然后不会立即求值,而是继续返回一个新函数,将传入的参数通过闭包的形式保存,等到被真正求值的时候,再一次性把所有传入的参数进行求值

//通用的柯里化函数
function curry(fn) {
    let slice = Array.prototype.slice,  // 将slice缓存起来
        args = slice.call(arguments, 1);   // 这里将arguments转成数组并保存

    return function() {
        // 将新旧的参数拼接起来
        let newArgs = args.concat(slice.call(arguments));    
        return fn.apply(null, newArgs); // 返回执行的fn并传递最新的参数
    }
}
// ES6版的柯里化函数
function curry(fn) {
    const g = (...allArgs) => allArgs.length >= fn.length ?
        fn(...allArgs) : 
        (...args) => g(...allArgs, ...args)

    return g;
}

// 测试用例
const foo = curry((a, b, c, d) => {
    console.log(a, b, c, d);
});
foo(1)(2)(3)(4);    // 1 2 3 4
const f = foo(1)(2)(3);
f(5);               // 1 2 3 5

反柯里化-函数的借用

简而言之就是函数的借用,天下函数(方法)大家用

//写法一
Function.prototype.uncurrying = function() {
    let self = this;    
    return function() {
        let obj = Array.prototype.shift.call(arguments);//删除并返回
        return self.apply(obj, arguments); 
    }
};
//写法二
Function.prototype.uncurrying = function() {
    let self = this;
    return function() {
        return Function.prototype.call.apply(self, arguments);
        /*相当于Function.prototype.call.apply(Array.prototype.slice, arguments);
        也就是相当于Array.prototype.slice.call(arguments)*/
    }
};

//测试一
let slice = Array.prototype.slice.uncurrying();

(function() {
    let result = slice(arguments);  
    console.log(result);    // [1, 2, 3]
})(1,2,3);

//测试二
let slice = Array.prototype.push.uncurrying();
let obj = {
    'length': 1,
    '0': 1
};
push(obj, 110);
console.log(obj);   // { '0': 1, '1': 110, length: 2 }
 [] === []//false 
 [] == []//false
 //因为[]是一个数组,是一个对象。就好比创建了2个对象,然后比较两个对象是否相同

[] == false//true
 /*他是经历了这个过程最终才为true的。
([] == false)   ---->  ([] == +0)   ---->  (“”== +0)  ---->  (+0 == +0)  --->   true*/

 window instanceof Object//false
 typeof(window) // object

typeof null === 'object';
null instanceof Object === false

null instanceof null//会抛出异常:``Uncaught TypeError: Right-hand side of 'instanceof' is not an object``

JS的基础类型Number,遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 bit。 1位用来表示符号位, 11位用来表示指数, 52位表示尾数

Math.pow(2, 53) == 9007199254740992 是可以表示的最大值.

Number.isSafeInteger(111111111111111110000)//false

//Firfox typeof g() //无输出响应 typeof g //undefined typeof f() //number typeof f //function

//IE8 typeof g() //number typeof g //function typeof f() //number typeof f //function


* 7 重点
```javascript
add(2, 5); // 7
add(2)(5); // 7
function addto(){
    var length = arguments.length;
    var sum = 0;
    for(var i = 0;i<length;i++){
        sum += arguments[i]
    }
    return sum;
}

function add(){
    var value = addto.apply(add,arguments);
    var helper = function(next){
        typeof next == "number" ? value+=next:value;
        return helper
    }
    helper.valueOf = function(){
        return value;
    }
    return helper;
}

什么是普通对象???

为什么result先输出????