call apply bind sleep

 

1.自己实现一个call
1)利用对象的方式的形式改变this指针  funcion add;  add.call(temObj)
只需要 在temObj对象临时添加一个方法即可
Function.prototype.mycall2=function(context){
    context.fn=this;
    context.fn();
    Reflect.deleteProperty(context,'fn')
}
2)call还可以携带实参传入
利用函数的arguments截取除了第一个即可
Function.prototype.mycall2=function(context){
    var args=[];
    for(var i=1;i<arguments.length;i++){
        args.push('arguments['+i+']')
    };
    debugger
    context.fn=this;
    context.fn(args);  //但是args是一个类数组
    Reflect.deleteProperty(context,'fn')
}
3)实现拆解函数的参数
将args这个类数组拆解为(args[0],args[1],....) Es6可以用扩展运算符
也可以用new Function
var result = new Function('context', 'arguments', 'context.fn(' + args + ')')(context, arguments)
Es3可以利用eval语法,eval中,args 自动调用 args.toString()方法;而数组中的toString的效果就是[].join(',')
var temArr=[1,2,3];
temArr.toString(); //1,2,3
temArr.join() //1,2,3
temArr.join=temArr.shift
temArr.toString()  //1
最终效果  context.fn(arguments[1], arguments[2], ...);
Function.prototype.mycall2=function(context){
    var args=[];
    for(var i=1;i<arguments.length;i++){
        args.push('arguments['+i+']')
    };
    context.fn=this;
    //context.fn(args);
    eval('context.fn('+args+')')
    Reflect.deleteProperty(context,'fn')
}

  function test(x,y){
    debugger;
    return console.log(x+y+this.name)
  }

  var temObj={name:'penguin'}

  test.mycall2(temObj,1,2)

 

4)实现当传null时候this指向window;还有有返回值
Function.prototype.mycall2=function(context){
    var context = context || window;
    var args=[];
    for(var i=1;i<arguments.length;i++){
        args.push('arguments['+i+']')
    };
    context.fn=this;
    var result=eval('context.fn('+args+')')
    Reflect.deleteProperty(context,'fn')
    return result
}

 

参考:https://github.com/mqyqingfeng/Blog/issues/11

实现一个apply
Function.prototype.myApply=function(context,arr){
    var context=context||window;
    context.fn=this;
    var args=[],result;

    for (var i = 0, len = arr.length; i < len; i++) {
      args.push('arr[' + i + ']');
    }

  if(!arr){
        result=context.fn()
    }else{
        result=eval('context.fn('+args+')');
    }
    return result;
}

 

 

1.自己实现一个bind函数
原理:通过apply或者call方法来实现。
(1)初始版本
Function.prototype.bind=function(obj,arg){
  var arg=Array.prototype.slice.call(arguments,1);
  var context=this;
  return function(newArg){
    arg=arg.concat(Array.prototype.slice.call(newArg));
    return context.apply(obj,arg);
  }
}

(2) 考虑到原型链
为什么要考虑?因为在new 一个bind过生成的新函数的时候,必须的条件是要继承原函数的原型
Function.prototype.bind=function(obj,arg){
  var arg=Array.prototype.slice.call(arguments,1);
  var context=this;
  var bound=function(newArg){
    arg=arg.concat(Array.prototype.slice.call(newArg));
    return context.apply(obj,arg);
  }
  var F=function(){}
  //这里需要一个寄生组合继承
  F.prototype=context.prototype;
  bound.prototype=new F();
  return bound;
}
如何实现sleep的效果(es5或者es6)
(1)while循环的方式
function sleep(ms){
   var start=Date.now(),expire=start+ms;
   while(Date.now()<expire);
   console.log('1111');
   return;
}

执行sleep(1000)之后,休眠了1000ms之后输出了1111。上述循环的方式缺点很明显,容易造成死循环。
(2)通过promise来实现
function sleep(ms){
  var temple=new Promise(
  (resolve)=>{
  console.log(111);setTimeout(resolve,ms)
  });
  return temple
}
sleep(500).then(function(){
   //console.log(222)
})
//先输出了111,延迟500ms后输出222

(3)通过async封装
function sleep(ms){
  return new Promise((resolve)=>setTimeout(resolve,ms));
}
async function test(){
  var temple=await sleep(1000);
  console.log(1111)
  return temple
}
test();
//延迟1000ms输出了1111

####(4).通过generate来实现
function* sleep(ms){
   yield new Promise(function(resolve,reject){
             console.log(111);
             setTimeout(resolve,ms);
        })  
}
sleep(500).next().value.then(function(){console.log(2222)})

 

Function._proto_(getPrototypeOf)是什么?
获取一个对象的原型,在chrome中可以通过__proto__的形式,或者在ES6中可以通过Object.getPrototypeOf的形式。
那么Function.proto是什么么?也就是说Function由什么对象继承而来,我们来做如下判别。
Function.__proto__==Object.prototype //false
Function.__proto__==Function.prototype//true
复制代码
我们发现Function的原型也是Function。

 

Function._proto_(getPrototypeOf)是什么?

获取一个对象的原型,在chrome中可以通过__proto__的形式,或者在ES6中可以通过Object.getPrototypeOf的形式。

那么Function.proto是什么么?也就是说Function由什么对象继承而来,我们来做如下判别。

Function.__proto__==Object.prototype //false
Function.__proto__==Function.prototype//true
复制代码

我们发现Function的原型也是Function。

 

posted @ 2019-06-27 18:28  little_ab  阅读(206)  评论(0编辑  收藏  举报