程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

Javascript中的this与call/apply/bind的关系

发布于2021-05-30 12:27     阅读(1242)     评论(0)     点赞(3)     收藏(1)


总结

  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

在浏览器里,在全局范围内:

  1. this等价于window对象;
  2. 用var声明一个变量和给this或者window添加属性是等价的;
  3. 如果你在声明一个变量的时候没有使用var或者let、const(es6),你就是在给全局的this添加或者改变属性值。
  1. // 1
  2. console.log(this === window); //true
  3. //2
  4. var name = "Jake";
  5. console.log(this.name ); // "Jake"
  6. console.log(window.name ); // "Jake"
  7. //3
  8. age = 23;
  9. function testThis() {
  10. age = 18;
  11. }
  12. console.log(this.age ); // 23
  13. testThis();
  14. console.log(this.age ); // 18

 总结起来就是:在全局范围内this是最大的,它等价于window对象(即指向window),如果你声明一些全局变量(不管在任何地方),这些变量都会作为this的属性。

函数中的 this

对于函数中的this的指向问题,运行时this永远指向最后调用它的那个对象。

举一个例子:

  1. var name = "windowsName";
  2. function sayName() {
  3. var name = "Jake";
  4. console.log(this.name); // windowsName
  5. console.log(this); // Window
  6. }
  7. sayName();
  8. console.log(this) // Window

 

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

需要注意的是,对于严格模式来说,默认绑定全局对象是不合法的,this被置为undefined。会报错 


如下面这个例子:

  1. function foo() {
  2. console.log( this.age );
  3. }
  4. var obj1 = {
  5. age : 23,
  6. foo: foo
  7. };
  8. var obj2 = {
  9. age : 18,
  10. obj1: obj1
  11. };
  12. obj2.obj1.foo(); // 23

还是开头的那句话,最后调用foo()的是obj1,所以this指向obj1,输出23

构造函数中的this

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

new的过程 例子:

  1. var a = new Foo("zhang","jake");
  2. new Foo{
  3. var obj = {};
  4. obj.__proto__ = Foo.prototype;
  5. var result = Foo.call(obj,"zhang","jake");
  6. return typeof result === 'obj'? result : obj;
  7. }

若执行 new Foo(),过程如下:
1) 创建新对象 obj;
2) 给新对象的内部属性赋值,构造原型链(将新对象的隐式原型指向其构造函数的显示原型);
3) 执行函数 Foo,执行过程中内部 this 指向新创建的对象 obj(这里使用了call改变this指向);
4) 如果 Foo 内部显式返回对象类型数据,则返回该数据,执行结束;否则返回新创建的对象 obj。
 

  1. var name = "Jake";jiuzhixiang
  2. function testThis(){
  3. this.name = 'jakezhang';
  4. this.sayName = function () {
  5. return this.name;
  6. }
  7. }
  8. console.log(this.name ); // Jake
  9. new testThis();
  10. console.log(this.name ); // Jake
  11. var result = new testThis();
  12. console.log(result.name ); // jakezhang
  13. console.log(result.sayName()); // jakezhang
  14. testThis();
  15. console.log(this.name ); // jakezhang

谁被new了,this就指向谁。 

 call、apply和bind中的this

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

  1. var name = 'zjk';
  2. function fun() {
  3. console.log (this.name);
  4. }
  5. var obj= {
  6. name: 'jake'
  7. };
  8. fun(); // zjk
  9. fun.call(obj); //Jake

上面的fun.ccall(obj)等价于fun.capply(obj)fun.cbind(obj)()

箭头函数中的this

“箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。" 

  1. let name = "zjk";
  2. let o = {
  3. name : "Jake",
  4. sayName: function () {
  5. console.log(this.name)
  6. },
  7. func: function () {
  8. setTimeout( () => {
  9. this.sayName()
  10. },100);
  11. }
  12. };
  13. o.func() // Jake

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

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

call/apply与bind的区别

  •   三者共同点:都是改变this指向的。
  •    不同的: call()/apply()----->bind()
  •   call() vs apply() 不同的:在于第二个参数,call第二个参数是一个一个的数据,apply第二个参数是数组。
  •   共同点:将this指向第一个参数。
  •   bind: bind只修改this指向,需要加()才能执行
  •   应用场景:伪数组借用数组方法  NodeList/arguments

 如下例:

  1. function fn() {
  2. console.log(arguments);
  3. 要往arguments集合中追加一个数100
  4. arguments.push(100);
  5. Array.prototype.push.call(arguments, 100)
  6. arguments集合中追加多个值,[100,200,300]
  7. Array.prototype.pop.call(arguments)
  8. [].pop.bind(arguments)();
  9. console.log(arguments);
  10. }
  11. fn(3, 4, 5, 6);

 

 

 

 

 

 

 

原文链接:https://blog.csdn.net/weixin_57983561/article/details/117262087




所属网站分类: 技术文章 > 博客

作者:Bhbvhbbgg

链接:http://www.qianduanheidong.com/blog/article/116065/1d4b33a660f36ba72efd/

来源:前端黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

3 0
收藏该文
已收藏

评论内容:(最多支持255个字符)