call/apply/bind

this的调用五种场景:
   1.浏览器里,在全局范围内的this 指向window对象;
   2.在函数中,this永远指向最后调用他的那个对象;
   3.构造函数中,this指向new出来的那个新的对象;
   4.Call、apply、bind中的this被强绑定在指定的那个对象上;
   5.箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.
前四种都是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;

6.apply、call、bind都是js给函数内置的一些API,调用他们可以为函数指定this的执行,同时也可以传参。


全局this

this等价于window对象;

用var声明一个变量和给this或者window添加属性是等价的;

如果你在声明一个变量的时候没有使用var或者let、const(es6),你就是在给全局的this添加或者改变属性值。

// 1
console.log(this === window); //true
//2
var name = "Jake";
console.log(this.name ); // "Jake"
console.log(window.name ); // "Jake"

//3
 age = 23;
 function testThis() {
   age = 18;
 }
 console.log(this.age ); // 23
 testThis();
 console.log(this.age ); // 18

在全局范围内this是大哥大,它等价于window对象,如果你声明一些全局变量,这些变量都会作为this的属性。

函数的 this

对于函数中的this的指向问题,有一句话很好用:运行时this永远指向最后调用它的那个对象。

var name = "windowsName";
function sayName() {
var name = "Jake";
console.log(this.name);   // windowsName
console.log(this);    // Window
}
sayName();
console.log(this) // Window

我们看最后调用 sayName的地方 sayName();,前面没有调用的对象那么就是全局对象 window,这就相当于是 window.sayName()。

需要注意的是,对于严格模式来说,默认绑定全局对象是不合法的,this被置为undefined。会报错 Uncaught TypeError: Cannot read property 'name' of undefined。

function foo() {
    console.log( this.age );
}

var obj1 = {
    age : 23,
    foo: foo
};

var obj2 = {
    age : 18,
    obj1: obj1
};

obj2.obj1.foo(); // 23

构造函数的this

所谓构造函数,就是通过这个函数生成一个新对象。当一个函数作为构造器使用时, 它的 this 值绑定到新创建的那个对象。如果没使用 new 关键字, 那么他就只是一个普通的函数, this 将指向 window 对象。

若执行 new Foo(),过程如下:
 创建新对象 obj;
 给新对象的内部属性赋值,构造原型链;
 执行函数 Foo,执行过程中内部 this 指向新创建的对象 obj;
 如果 Foo 内部显式返回对象类型数据,则返回该数据,执行结束;否则返回新创建的对象 obj。

var name = "Jake";jiuzhixiang
function testThis(){
  this.name = 'jakezhang';
  this.sayName = function () {
        return this.name;
    }
}
console.log(this.name ); // Jake

new testThis(); 
console.log(this.name ); // Jake

var result = new testThis();
console.log(result.name ); // jakezhang
console.log(result.sayName()); // jakezhang

testThis();  
console.log(this.name ); // jakezhang

谁被new了,this就指向谁。

class的this

在es6中,类,是 JavaScript 应用程序中非常重要的一个部分。类通常包含一个 constructor , this可以指向任何新创建的对象。
不过在作为方法时,如果该方法作为普通函数被调用, this也可以指向任何其他值。与方法一样,类也可能失去对接收器的跟踪。

class Hero {
  constructor(heroName) {
    this.heroName = heroName;
  }
  dialogue() {
    console.log(`I am ${this.heroName}`)
  }
}
const batman = new Hero("Batman");
batman.dialogue();

构造函数里的 this指向新创建的 类实例。当我们调用 batman.dialogue()时, dialogue()作为方法被调用, batman是它的接收器。
但是如果我们将 dialogue()方法的引用存储起来,并稍后将其作为函数调用,我们会丢失该方法的接收器,此时 this参数指向 undefined

call、apply和bind的this

call、apply、bind 被称之为 this 的强绑定,用来改变函数执行时的this指向,目前所有关于它们的运用,都是基于这一点来进行的。

箭头函数this

es5中的this要看函数在什么地方调用(即要看运行时),通过谁是最后调用它该函数的对象来判断this指向。但es6的箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this 为 undefined。箭头函数的 this 始终指向函数定义时的 this,而非执行时。

  let name = "zjk";

    let o = {
        name : "Jake",

        sayName: function () {
            console.log(this.name)     
        },

        func: function () {
            setTimeout( () => {
                this.sayName()
            },100);
        }

    };

    o.func()     // Jake

使用 call 、 apply或 bind等方法给 this传值,箭头函数会忽略。箭头函数引用的是箭头函数在创建时设置的 this值。

let obj = {
  name: "Jake",
  func: (a,b) => {
      console.log(this.name,a,b);
  }
};
func.call(obj,1,2);// 1 2
func.apply(obj,[1,2]);//  1 2

call & apply

每个函数都包含两个非继承而来的方法:apply()和 call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值。

apply()

apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是 Array 的实例,也可以是arguments 对象。

function sum(num1, num2){ 
 return num1 + num2; 

function callSum1(num1, num2){ 
 return sum.apply(this, arguments); // 传入 arguments 对象

function callSum2(num1, num2){ 
 return sum.apply(this, [num1, num2]); // 传入数组

console.log(callSum1(10,10)); //20
console.log(callSum2(10,10)); //20

在严格模式下,未指定环境对象而调用函数,则 this 值不会转型为 window。除非明确把函数添加到某个对象或者调用 apply()或 call(),否则 this 值将是undefined。

call()

call()方法与 apply()方法的作用相同,它们的唯一区别在于接收参数的方式不同。在使用call()方法时,传递给函数的参数必须逐个列举出来。

function sum(num1, num2){ 
 return num1 + num2; 
}
function callSum(num1, num2){ 
 return sum.call(this, num1, num2); 

console.log(callSum(10,10)); //20

call()方法与 apply()方法返回的结果是完全相同的,至于是使用 apply()还是 call(),完全取决于你采取哪种给函数传递参数的方式最方便。

bind()

bind()方法会创建一个函数的实例,其 this 值会被绑定到传给 bind()函数的值。意思就是 bind() 会返回一个新函数。例如

window.color = "red"; 
var o = { color: "blue" }; 
function sayColor(){ 
 alert(this.color); 

var objectSayColor = sayColor.bind(o); 
objectSayColor(); //blue

call/apply与bind的区别

执行:

call/apply改变了函数的this上下文后马上执行该函数

bind则是返回改变了上下文后的函数,不执行该函数

function add (a, b) {
    return a + b;
}

function sub (a, b) {
    return a - b;
}

add.bind(sub, 5, 3); // 这时,并不会返回 8
add.bind(sub, 5, 3)(); // 调用后,返回 8

返回值:

call/apply 返回fun的执行结果
bind返回fun的拷贝,并指定了fun的this指向,保存了fun的参数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值