💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
~~~ let 与var区别 1. 变量提升; 2. 重复声明; 3. let 声明的和Window没有关系; 4. 暂时性死区; 5. let 可以形成块级作用域; 严格模式this是undefined 构造函数,this是当前类的实例 /* * 用来改变某一个函数中THIS关键字指向的 * call * apply * bind */ window.name = '珠峰'; let fn = function () { console.log(this.name); }; let obj = { name: "OBJ", fn: fn // obj 有个属性叫fn,fn的值是fn函数 }; let oo = {name: "OO"}; // fn();//=>this:window "珠峰" // obj.fn();//=>this:obj "OBJ" oo.fn() // 报错 fn.call(oo) //oo ~~~ ![](https://img.kancloud.cn/51/11/51115cc049a7494143fa44ad8a062361_435x258.png) ~~~ /* * call * 1. [fn].call([this],[param]...) * fn.call:当前实例(函数FN)通过原型链的查找机制,找到 * Function.prototype上的call方法 =>function call(){[native code]} * * fn.call():把找到的call方法执行 * * 当call方法执行的时候,内部处理了一些事情 * =>1。首先把要操作函数中的THIS关键字变为CALL方法第一个传递的实参值 * =>2。把CALL方法第二个及第二个以后的实参获取到 * =>3。把要操作的函数执行,并且把第二个以后的传递进来的实参传给要操作的函数 * fn.call(obj,10,20,30) 10,20,30传给fn */ var ary = []; ary.slice; ary.__proto__slice; //ary这个实例直接通过__proto__找到Array这个原型slice fn.call ; // 找到方法 fn.call(); //找到并执行; // fn.call(oo);//=>this:oo // fn.call(obj,10,20,30);//=>this:obj ,把fn中的this改成call中的第一个参数 /*Function.prototype.call = function () { let param1 = arguments[0], paramOther = [];//=>把ARG中除了第一个以外的实参获取到 //=>this:fn 当前要操作的函数(函数类的一个实例) //把FN中的THIS关键字修改为PARAM1 => 把THIS(CALL中)中的this关键字修改为param1 //=>把fn执行,把paramOther分别传递给fn // this(paramOther) =>fn(paramOther) }; fn.call({name:'xx'}) sum.call({..}) */ let sum=function(a,b){ console.log(this);//=>opt }; let opt={n:20}; // sum.call(opt,20,30);//=>call执行 call中的this是sum 把this(call中的)中的“this关键字”改为opt 把this(call中的)执行, 把20,30分别传递给它 //=>sum中this:opt a=20 b=30 sum.call.call(opt) //1.sum.call 找到Function.prototype上的call方法(也是一个函数, 也是函数类的一个实例,也可以继续调用call/apply等方法) =>A(函数) //2.A.call(opt) 继续找到原型上的call方法,把call方法执行: 把A中的this关键字修改为opt,然后把A执行 ~~~ ~~~ /* Function.prototype.call=function callAA(){ //=>1.把THIS(FN)中的"THIS关键字"修改为第一个参数值(OBJ) //=>2.把THIS(FN)执行,把第二个及以后接受的参数值传递给函数(10,20) //this(10,20) }; fn.call(obj,10,20) */ function fn1(){console.log(1);} //么有this function fn2(){console.log(2);} fn1.call(fn2);//=>找到CALL-AA把它执行,CALL-AA中的THIS是FN1, 第一个参数传递的是FN2 =>在CALL-AA中执行的是FN1 =>1 fn1.call.call(fn2);//=>找到CALL-AA让它执行,CALL-AA中的THIS是FN1.CALL, 第一个参数是FN2 (把FN1.CALL中的THIS变为FN2,再让FN1.CALL执行 =>先找到CALL-AA,把它执行,只不过此时它中的THIS是FN2 =>让FN2中的THIS变为UNDEFINED,因为执行FN1.CALL的时候没有传递参数值, 然后让FN2执行) =>2 Function.prototype.call(fn1);//=>先找到CALL-AA把它执行, 它中的THIS是Function.prototype =>让F.P中的THIS变为FN1,然后让F.P执行, F.P是一个匿名函数也是一个空函数,执行没有任何的输出 Function.prototype.call.call(fn1);//=>先找到CALL-AA把它执行,它中的THIS是F.P.CALL =>把F.P.CALL中的THIS修改为FN1,让F.P.CALL执行 =>F.P.CALL(CALL-AA)第二次把它执行(此时它里面的THIS已经是FN1) =>这一次其实在CALL-AA中是让FN1执行 =>1 //<==> fn1.call.call(fn2) //<==> fn1.call===Function.prototype.call :true fn1.call.call.call.call.call(fn2); //=>fn1.call.call.call.call===Function.prototype.call ~~~ **一个call执行前面的,2个2个以上,让后面的执行 ** ![](https://img.kancloud.cn/b8/d9/b8d937687020e4e03c04686c2207c2b6_1121x440.png)