call,appyとbind

19169 ワード

thisを学ぶ時、いくつかの方法のcallを見ました.applyとbindにもう一つのnew演算子があります.それらの概念と原理を勉強しました.
Funtion.prototype.cal()
function.call(thisArg,arg 1,arg 2...)関数は、指定されたthis値と個別に与えられた1つ以上のパラメータを使用して呼び出されます.戻り値は、this値とパラメータが指定された関数を呼び出した結果です.厳密でないモードでは、thisArgがnullまたはundefinedであれば、自動的にグローバルオブジェクト2.thisArgに置き換えられます.コールは自動的に元のデータタイプに変換されます.
// call   
var animals = [
  {
      species: 'Lion', name: 'King' },
  {
      species: 'Whale', name: 'Fail' }
];

for (var i = 0; i < animals.length;i++){
     
  (function (i) {
     
    this.point = function () {
     
      console.log(`#${
      i}:${
      this.species}+${
      this.name}`)
    }
  }).call(animals[i],i)
}
//               
原理
Function.prototype.myCall = function (context) {
     
    /**             null     undefined,     this   window/global */
    /**             null   undefined,           */
    if (!context) {
     
        //         window  global
        context = typeof window === 'undefined' ? global : window;
    }else{
     
     	context = Object(context)
    }
    context.fn = this; //this         (Function   )
    let rest = [...arguments].slice(1);//    this         ,    slice          
    let result = context.fn(...rest); //    ,     this   context.
    delete context.fn; //     
    return result; //          
}

テスト
var foo = {
     
    name: 'Selina'
}
var name = 'Chirs';
function bar(job, age) {
       
    console.log(this.name);
    console.log(job, age);
}
bar.myCall(foo, 'programmer', 20); //Selina, programmer , 20
bar.myCall(null, 'programmer', 20); //Chirs, programmer , 20
Function.prototype.apple()
function.applyは、指定されたthis値と配列オブジェクト(またはクラスオブジェクト)を使用して関数を呼び出します.非厳密モードでは、thisArgがnullまたはundefinedであれば自動的にグローバルオブジェクトに置き換えられ、戻り値は、指定されたthis値とパラメータの関数を呼び出した結果です.
//   apply                   
let charArr = ['a','b','c']
let numArr = [1,2,3]
numArr.push.apply(numArr,charArr)
console.log(numArr) //[1 , 2 , 3 , 'a' , 'b' ,'c']
原理はコールに似ています.
Function.prototype.myApply = function(context,rest){
     
    //                           
    if(!context){
     
        // call  ,        null   undefined   ,        
        context = typeof window === undefined ? global : window
    }else{
     
     	context = Object(context)
    }
    context.fn= this 
    let result;
    if(rest === undefined || rest === null){
     
        //      undefined   null     ...
        result = context.fn(rest)
    } else if (rest instanceof Object ){
     
        result = context.fn(...rest)
    }
    delete context.fn //     
    return result
}
テスト
//    
var foo = {
     
    name: 'Selina'
}
var name = 'Chirs';
function bar(job, age) {
     
    console.log(this.name);
    console.log(job, age);
}
bar.myApply(foo, ['programmer', 20]); //Selina programmer 20
bar.myApply(null, 'teacher', 25);
//     : Chirs teacher 25; node   : undefined teacher 25
Function.prototype.bind()
function.bindは新しい関数を作成します.新しい関数のthisはbindの最初のパラメータに指定されます.残りのパラメータは新しい関数のパラメータとして、ソース関数のコピー関数を返して、指定されたthis値とパラメータを持ちます.したがって、bindを呼び出すには関数3が必要です.newを使って、bindから返される関数を呼び出した場合、thisはソース関数構造関数の例を指します.
Function.prototype.myBind = function (thisArg,...rest) {
     
	//            
  if (typeof this !== 'function') throw new TypeError("invalid invoked!");
  let self = this
  //          
  return function F(...args) {
     
    console.log(this)
    if(this instanceof F){
     
      //           new      this            
      return new self(...rest,...args)
      //               
    }
    //          
    return self.apply(thisArg,[...rest,...args])
  }  
}
テスト
var name = 'window'
function fn(name) {
     
  // console.log(this)
  console.log(this.name)
  console.log(name)
}

let obj = {
     
  name:'obj'
}
let f= fn.myBind(obj)
f('  ') //obj   

let nF = new f('  ') // undefined    
new操作子
new constructor[(argments)]constructorの指定されたインスタンスのタイプのクラスまたは関数argmentsパラメータリストnew演算子がユーザ定義のオブジェクトタイプのインスタンスを作成するか、または構築関数内蔵のオブジェクトのインスタンスnewキーワードが次の操作を行います.
  • 新しいオブジェクトを作成します.
  • このオブジェクトの_uをプロト.この構造関数を指すプロトタイプ
  • このオブジェクトを関数とするthisのコンテキスト
  • このコンストラクションがオブジェクトに戻らない場合、この新しいオブジェクト
  • に戻ります.
    function Person(name,age) {
         
      this.name = name
      this.age = age
    }
    let p = new Person('  ',23)
    console.log(p) //Person {
          name: '  ', age: 23 }
    
    原理
    function myNew(fun, ...arg) {
         
        //         
        const result = {
         };
        //     __proto__            
        result.__proto__ = fun.prototype
       	fun.prototype.constructor  == fun
        //       (this)          
        const res = fun.apply(result, arg);
        //             
        if(res&&res instanceof Object){
         
            return res
        }
        //             
        return result;
    }
    
    テスト
    function Person(name,age) {
         
      this.name = name
      this.age = age
    }
    
    let p = myNew(Person,'  ',22)
    console.log(p) //Person {
          name: '  ', age: 22 }
    
    function Person(name,age) {
         
      this.name = name
      this.age = age
      return {
         }
    }
    
    let p = myNew(Person,'  ',22)
    console.log(p) //{
         }