You Don‘t Know JS(一)

1 篇文章 0 订阅
1 篇文章 0 订阅

1.JS柯里化

概念
百度百科:在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。通俗点说就是将一个函数拆分成多个函数,是固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩小适用范围,创建一个针对性更强的函数;

  • 问题

如何实现一个函数满足sum(1,2,3,4,5,6)或sum(1)(2)(3)(4)(5)(6)输出结果都为21?

function sum() {

        var args = [...arguments]; 
        //针对()()()这类调用方式,利用必包特性将参数存储 
        var _sum = function() { 
           args = [...args, ...arguments];
            return _sum;
        }
        //自执行函数,计算参数之和
        _sum.toString = function() {
            const v = args && args.length && args.reduce((a, b) => a + b) 
            return v;
        }
        return _sum;
    }

   var v =  sum(1,2,3,4,5,6);
   var b = sum(1)(2)(3)(4)(5)(6);
   
   console.log(v, 'sum',b)  //21 sum  21

2.防抖

当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。

3.节流

当持续触发事件时,保证在一定时间内只调用一次事件处理函数。

问题
如何实现一个防抖函数?
如何实现一个节流函数?

  • 防抖
var timer1 = null;
function clickFn(time) { 
    if (timer1 != null)  clearTimeout(timer1);
    timer1 = setTimeout(function() {
        console.log('防抖')
    },time) 
} 
  • 节流
var timer = null;
function clickFn2(time) {
    if (!timer) {
        timer = setTimeout(function() {
            console.log('节流');
              timer = null;
        }, time)
     } 
  }

4.如何实现一个变量a,满足 a == 1 && a == 2 && a == 3或者a=1 && a=2&&a===3返回true?

//此种可以满足严格和宽松两种等模式
var i = 1;
Object.defineProperty(window, 'a', {
            get() {return i++}
})

//此种模式或toString方式只能满足宽松模式==,严格模式下不会进行数据转换,直接对值进行比较
var a = {
    i: 1,
    valueOf() {
         return this.i++
   }
}

5.void 0 与undefined区别?

  1. void 0 替换undefined后能节省不少字节的大小;
  2. undefined在低版本 IE 中可以重写如: var undefined = 10; 这样会影响代码中undefined的判断;
  3. undefined 在 ES5 中已经是全局对象的一个只读(read-only)属性了,它不能被重写。但是在局部作用域中,还是可以被重写的。 (function() { var undefined = 10; // 10 -- chrome alert(undefined); })();
  4. void 运算符能对给定的表达式进行求值,然后返回 undefined,也就是说,void 后面你随便跟上一个表达式,返回的都是
    undefined,都能完美代替 undefined!那么,这其中最短的是什么呢?毫无疑问就是 void 0 了;void是不能被重写的;

6.call、apply、bind共同点及区别?如何手动实现以上三个函数?

共同点: 三者都是改变函数体内this的指向;
不同点:
call、apply的区别:接受参数的方式不一样,call(fn, p1,p2,p3…),apply(fn,[p1,p2,p3…])为数组, 返回函数执行结果;
bind:不立即执行。而apply、call 立即执行。返回函数的拷贝,并拥有指定的this和初始参数;

  • apply实现
Function.prototype.MyApply = function(context) {
    if (typeof this !== 'function') {
        throw new TypeError('not function!');
    }
    context = context || window;
    context.fn = this;
    let result;
    if (arguments[1]) {
        result = context.fn(...arguments[1])
    } else {
        result = context.fn()
    }
    delete context.fn;
    return result;
 }
  • call实现
Function.prototype.MyCall = function(context) {
    //判断当前是否函数调用
    if (typeof this !== 'function') {
        throw new TypeError('not funciton');
    } 
    context = context || window;
    context.fn = this;
    let args = [...arguments].slice(1); 
    let result = context.fn(...args); 
    delete context.fn;
    return result; 
 }
  • bind实现
Function.prototype.MyBind = function(context) {
    if (typeof this !== 'function') {
        throw new TypeError('not function!');
    }
    let _this = this
    let arg = [...arguments].slice(1);
    return function F() {
        // 处理函数使用new的情况
        if (this instanceof F) {
          return new _this(...arg, ...arguments)
        } else {
          return _this.apply(context, arg.concat(...arguments))
        }
    }
}
  • 拓展bind使用场景

想让下面代码输出1,2,3,4,5?

for (var i = 1; i <= 5; i++) {
    setTimeout(function test() {
        console.log(i) // 依次输出:6 6 6 6 6
    }, i * 1000);
}

闭包实现?

for (var i = 1; i <= 5; i++) {
        (function (i) {
            setTimeout(function () {
                console.log('闭包:', i); // 依次输出:1 2 3 4 5
            }, i * 1000);
        }(i));
}

bind实现?

for (var i = 1; i <= 5; i++) {
        // 缓存参数
        setTimeout(function (i) {
            console.log('bind', i) // 依次输出:1 2 3 4 5
        }.bind(null, i), i * 1000);
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ai4code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值