this, bind,call,apply 面试题

了解 this 嘛,bind,call,apply 具体指什么

它们都是函数的方法

call: Array.prototype.call(this, args1, args2]) apply: Array.prototype.apply(this, [args1, args2]) :ES6 之前用来展开数组调用, foo.appy(null, []),ES6 之后使用 ... 操作符

  • New 绑定 > 显示绑定 > 隐式绑定 > 默认绑定
  • 如果需要使用 bind 的柯里化和 apply 的数组解构,绑定到 null,尽可能使用 Object.create(null) 创建一个 DMZ 对象

四条规则:

  • 默认绑定,没有其他修饰(bind、apply、call),在非严格模式下定义指向全局对象,在严格模式下定义指向 undefined
function foo() {
 	console.log(this.a); 
}

var a = 2;
foo();
  • 隐式绑定:调用位置是否有上下文对象,或者是否被某个对象拥有或者包含,那么隐式绑定规则会把函数调用中的 this 绑定到这个上下文对象。而且,对象属性链只有上一层或者说最后一层在调用位置中起作用
function foo() {
  console.log(this.a);
}

var obj = {
  a: 2,
  foo: foo,
}

obj.foo(); // 2
  • 显示绑定:通过在函数上运行 call 和 apply ,来显示的绑定 this
function foo() {
  console.log(this.a);
}

var obj = {
  a: 2
};

foo.call(obj);

显示绑定之硬绑定

function foo(something) {
  console.log(this.a, something);
  
  return this.a + something;
}

function bind(fn, obj) {
  return function() {
    return fn.apply(obj, arguments);
  };
}

var obj = {
  a: 2
}

var bar = bind(foo, obj);

New 绑定,new 调用函数会创建一个全新的对象,并将这个对象绑定到函数调用的 this。

  • New 绑定时,如果是 new 一个硬绑定函数,那么会用 new 新建的对象替换这个硬绑定 this,
function foo(a) {
  this.a = a;
}

var bar = new foo(2);
console.log(bar.a)

(4)问:手写 bind、apply、call

// call

Function.prototype.call = function (context, ...args) {
  context = context || window;
  
  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;
  
  context[fnSymbol](...args);
  delete context[fnSymbol];
}
// apply

Function.prototype.apply = function (context, argsArr) {
  context = context || window;
  
  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;
  
  context[fnSymbol](...argsArr);
  delete context[fnSymbol];
}
// bind

Function.prototype.bind = function (context, ...args) {
  context = context || window;
  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;
  
  return function (..._args) {
    args = args.concat(_args);
    
    context[fnSymbol](...args);
    delete context[fnSymbol];   
  }
}
    



// MDN的标准源码
if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      // closest thing possible to the ECMAScript 5 internal IsCallable function
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var aArgs = Array.prototype.slice.call(arguments, 1), 
        fToBind = this, 
        fNOP = function () {},
        fBound = function () {
          return fToBind.apply(this instanceof fNOP && oThis
                                 ? this
                                 : oThis || window,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };
}

测试test:

Function.prototype.myCall = function (context) {console.log('this',this)}
var obj = {a:1}

aaa.myCall(obj)

// 输出
// this ƒ aaa(obj){alert(obj)}

猜你喜欢

转载自blog.csdn.net/lianjiuxiao/article/details/114886697
今日推荐