Front-end JavaScript basic learning method (2)

一、call,apply,bind

call, apply, bind are all used to change this point

the difference:

Different parameters

call pass parameters in comma separated form

Function name.call (target object, parameter 1, parameter 2, ... parameter n)

For example: getName.call(obj,'王五',25,'Beijing')

apply parameters are passed in the form of an array

Function name.apply (target object, [parameter 1, parameter 2, ... parameter n])
For example: getName.apply(obj,['王五11',25,'Shanghai'])

Bind uses commas to pass parameters

Whether getName.bind(obj,'王五11',25,'Shanghai')() or getName.bind(obj)('王五11',25,'Shanghai')
function is executed

cal and apply directly call the function
bind is to return the function itself, if you want to execute, you must add () call
getName.bind(obj)()
call, apply implementation principle

The realization principle of call (no need to call, manually simulate the function of a call)

call是基于函数实现的
给作用的目标对象添加一个临时函数,处理赋值操作
接收参数处理
最后再删除这个临时函数
实例化对象=new 构造函数() //其中构造函数也称为类,一个类可以生成多个实例化对象

var f1=new Function() // 其中的构造函数中this===f1 永远相等
var p1=new Person() //其中的构造函数中this===p1 永远相等
//call模拟实现原理代码:
Function.prototype.call2 = function (context) {
    
    
    //目标对象
    context = context || window;

    //this===实例化的函数,函数本质上也是对象

    //给context添加一个临时函数
    context.fn = this;

    //接收参数处理  arguments
    console.log('arguments:',arguments)
    var args = [];
    for (var i = 1; i < arguments.length; i++) {
    
    

       // ["arguments[0]", "arguments[1]", "arguments[2]"]
        args.push('arguments['+i+']')
       // args.push(arguments[i])
    }

     //传参执行context.fn()函数
     eval('context.fn(' + args + ')')
    
    
    //删除临时函数
    delete context.fn

    
}

Apply implementation principle
Function.prototype.apply2 = function (context,arr) { //Target object context = context || window;

//this===实例化的函数,函数本质上也是对象

//给context添加一个临时函数
context.fn = this;

if (!arr) {
    context.fn()
} else {
    //接收参数处理  arguments
    var args = [];
    for (var i = 0; i < arr.length; i++) {

    // ["arguments[0]", "arguments[1]", "arguments[2]"]
        args.push('arr['+i+']')
    // args.push(arguments[i])
    }

    //传参执行context.fn()函数
    eval('context.fn(' + args + ')')


 }

//删除临时函数
delete context.fn

}

Bind implementation principle

var obj = {
    
    
    init: 1,
    add: function(a, b) {
    
    
        return a + b + this.init;
    }
}
obj.add(1, 2); // 4
 
var plus = obj.add;
plus(3, 4); // NaN,因为 this.init 不存在,这里的 this 指向 window/global
 
plus.call(obj, 3, 4) // 8
plus.apply(obj, [3, 4]); // 8, apply 和 call 的区别就是第二个参数为数组
plus.bind(obj, 3, 4); // 返回一个函数,这里就是 bind 和 call/apply 的区别之一,bind 的时候不会立即执行

The summary
is simply to use bind to change the this point. The difference between call/apply has a delayed execution effect

Second, the realization principle of new

Features of new

  1. new a constructor, will automatically reutrn an instantiated object
  2. The new instantiated object __proto___ automatically points to the prototype of the constructor
  3. The new constructor passes parameters and automatically assigns values ​​to the current instantiated object

Three, anti-shake and throttling

Anti-shake concept

If there is no trigger event in a fixed time, it will be triggered after the fixed time is over. If the event is triggered within a fixed time, it will be triggered again after a fixed time.
Anti-shake is mainly realized by timer

//用定时器实现防抖
function debounce(func,wait) {
    
    
    var timer=null;
    return function() {
    
    
    //保存当前调用的dom对象
     var _this=this;
     //保存事件对象
     var args=arguments;
     clearTimeout(timer)
     timer=setTimeout(function() {
    
    
         func.apply(_this,args)
     },wait)
    }

}

Throttling concept:

Regardless of whether there is an event triggered within a fixed time, it will be triggered according to the fixed time rule

There are two methods for specific implementation

The first type: timestamp

//时间戳版本实现节流
function throttle(func,wait) {
    
    
    //定义初始时间
    var oldTime=0;

    return function() {
    
    
        var _this=this;
        var args=arguments;

        //当前时间戳
        var newTime=+new Date();

        //判断用当前时间减去旧的时间,如果大于wait指定的时间就会触发
        if(newTime-oldTime>wait) {
    
    
            //执行触发的函数
            func.apply(_this,args)
            //将旧时间更新
            oldTime=newTime;
        }

    }

The second type: timer

//时间戳版本实现节流
function throttle(func,wait) {
    
    
    var timer=null;

    return function() {
    
    
        var _this=this;
        var args=arguments;
       if(!timer) {
    
    
            timer=setTimeout(function() {
    
    
                timer=null;
                func.apply(_this,args)
            },wait)
       }
    }
}

Of course, if you are not proficient in the above, you can use the current mainstream tool library: lodash has provided a comprehensive tool method

For details, please refer to the lodash website: https://www.lodashjs.com/

Guess you like

Origin blog.csdn.net/weixin_48193717/article/details/108328759