this指针绑定

this概念

this是指当前函数,当前模块的运行环境上下文。是一个指针变量,普通函数的this是在调用时才被绑定确认指向的(即是谁调用就指向谁);

下面介绍几种this绑定规则

一、默认绑定

   特点:非严格模式下  this指向全局对象(浏览器环境里指向window,  node环境里指向global)

        严格模式下    this指向undefined,严格模式下是不允许this指向全局对象的。

function a(){};
   a(); // 函数独立调用,不带任何修饰函数的引用

   var name = '哈哈哈';
   var obj = {
    name:'张三',
    fun:function(){
      // 'use strict' // 严格模式
      console.log(this.name);
    }
   }
   var p1 = obj.fun;
   p1(); // 哈哈哈(严格模式下会报错Uncaught TypeError: Cannot read properties of undefined (reading 'name'))
   // 这个例子是典型的默认绑定,关注点不要放在obj对象上,而要关注 函数最终调用的形式,p1的调用就是独立调用不加任何修饰的,所以指向全局window

 二、隐式绑定(与默认绑定相反,函数调用前面有修饰,谁调用函数,this就指向谁)

   普通函数作为参数传递的情况,setTimeout,setInterval,非严格模式下this指向全局对象

   var name = '张三';
   var person = {
     name : '李四',
     fun:fun
   }
   function fun(){
     console.log(this.name) // 李四
    // 普通函数
     setTimeout(function(){
       console.log(this.name) // 张三
     })
    // 箭头函数
    setTimeout(()=>{
      console.log(this.name) // 李四
    })
   }
   person.fun();

        链式调用

// 链式调用
  function fun(){
    console.log(this.name)
  }
  var p1 = {
    name:"zhangsan",
    fun:fun
  }
  var p2 = {
    name:"hahah",
    xixi:p1 // 关联p1
  }
  p2.xixi.fun(); // zhangsan // this 指向 p1(链式调用this指向保持就近原则)

 三、显示绑定 call apply bind(都可修改函数的this指向)

call 和 apply 的异同点

    1、都是改变this指向的

    2、第一个参数都是作为this指向的,如果不传参 fun.call(),非严格模式下this会绑定到全局对象上

    3、区别就是第二参数形式。call是一个一个的列表形式,apply是数组的形式

    例: a.call(b,'sing','eat')   a(1,['hahah','xixii'])

 var person = {
      name:'张三'
    }
    function chang_this(hob,state){
      this.hob = hob;
      this.state = state; // 改变this指向后相当于 person.hob = hob  person.state = state
    }
    chang_this.call(person,'sing','eat') // 改变this指向person
    console.log(person) // {name: '张三', hob: 'sing', state: 'eat'}
    chang_this.apply(1,['hahah','xixii']) // 改变this指向person
    console.log(person) // {name: '张三', hob: 'hahah', state: 'xixii'}


    /* call和apply如果传递的第一个参数是数字或者字符串  的情况*/
    function readayThisType(){
      console.log(typeof this)
    }
    readayThisType(1); // [Number:1] object // 解析成为数字类型的对象
    readayThisType('haha'); // [String: 'haha ]object // 解析成为字符串类型的对象

    /* bind
    1、 bind方法会创建一个新的函数
    2、当这个新函数被调用时,bind的第一个参数,会作为函数运行时候的this
    3、之后的 一系列参数 都会在 传递实参前 传入 作为它的参数
    */
   var obj = {
     name:'原有',
     state:'eat',
     fun : function(str){
       console.log(`${str} ${this.name}`)
     }
   }
   obj.fun('haha'); // haha 原有
   var nextObj = obj.fun.bind({name:'新传', state:'run'},'xixi')
   nextObj(); // xixi 新传(之前说的默认绑定指向全局是不严谨的,应该有优先级)

四、new

 1.创建一个空对象

   2、将空对象的__proto__指向原型对象的prototype

   3、以新对象为this执行原有的构造函数

   4、return  

function parent(name){
    this.name = name;// 通过new 将构造函数的 this 指向new出来的实例
  }
  var p1 = new parent('zhansan')
  console.log(p1.name) // zhansan
  // 通过new 将构造函数的 this 指向new出来的实例  p1

 this绑定的优先级

    new绑定 > 显示绑定(bind,call,apply) > 隐式绑定(obj.fun)>默认绑定(没有任何修饰,直接调用)

关于优先级  来看下面一段代码

 // 测试代码
 function foo(a){
  this.a = a;
 }
 var obj1 = {
   foo:foo
 }
 var obj2 = {};

 obj1.foo(2);
 console.log(obj1.a) // 2

 obj1.foo.call(obj2,3);
 console.log(obj2.a); // 3

 var bar = new obj1.foo(4);
 //  通过new 将构造函数的 this 指向new出来的实例  bar   相当于是 function foo(){ bar.a = a;}
 // 所以 下面两个打印 不会改变 obj1 对象,只会改变 实例 bar 上的属性
 console.log(obj1.a);// 2 
 console.log(bar.a); // 4

五、箭头函数

 

// 验证箭头函数特性
 let funs = ()=>{};
 console.log(funs.prototype)// undefined  // 3.箭头函数没有原型对象
 console.log(funs.prototype.constructor) // 报错 Cannot read properties of undefined ();2.没有prototype 更没有prototype.constructor
// 箭头函数代码
 var name = '张三';
   var person = {
     name : '李四',
     fun:fun
   }
   function fun(){
     console.log(this.name) // 李四
    // 普通函数
     setTimeout(function(){
       console.log(this.name) // 张三
     })
    // 箭头函数
    setTimeout(()=>{
      console.log(arguments) // fun的参数
      console.log(this.name) // 李四   在fun函数的上下文中,箭头函数的this就是fun函数的this
    })
   }
   person.fun();

  面试题:

 var name = '123';
   var obj = {
     name:'456',
     init:function(){
       function a(){
         console.log(this.name) // 123
       }
       a(); // 因为函数a和函数p都有自己的this,最终是这里调用  是默认绑定
     }
   }
   obj.init();
   //==========================================================================================
   var length = 12;
   function fn(){
     console.log(this.length);
   }
   var obj = {
     length :6,
     fn:function(fn){
      fn(); // 12
      arguments[0](); // 2      分解:arguments:[fn,1]  length为2
      // arguments[0]就是传入的fn函数  然后再执行fn()console.log(this.length),指向调用者arguments伪数组(对象)
     }
   }
   obj.fn(fn,2)

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值