前端必须理解this的相关知识

510 阅读2分钟

一、对this的产生原因分析和了解

1.this指的是函数运行时所在的环境(即调用的对象)。
2.JavaScript 语言之所以有this的设计,跟内存里面的数据结构有关系

二、this绑定详解

this 实际上是在函数被调用时发生的绑定,它指向什么地方完全取决于函数在哪里被调用。

1.默认绑定

	function foo(){
	    var a = 1 ; //局部变量
	    console.log(this.a);   
	}
	var a = 10;  //全局变量
	foo(); //window.foo()

2.隐性绑定

var a = 10;  //全局变量
function foo(){
    var a = 1 ; //局部变量
    console.log(this.a);   
}
var obj = {
    a : 20,
    foo : foo
}
obj.foo(); //window.obj.foo() 

3.显示绑定apply,call,bind 这个三个函数都是改变this指向

    (1)call
  
	var box=document.getElementById('box')
	
	box.onclick = function(){
		console.log(this)  //指向box元素
      function boxFn(params1,params2,params3){
          console.log(this) 
      }
		boxFn() 
		boxFn.call(this,1,2,3) //call改变this指向,将this指向box元素
	}

    (2)apply

    var applayObj1={
        name:'张三'
    }
    
    var applayObj={
        name:'李四',
        applayFun(param1,param2,param3){
          console.log(this.name)
        }
    }
    
    var applayfun2=applayObj.applayFun
    
    applayObj.applayFun() //window.applayObj.applayFun()
    
    applayfun2.apply(this,[1,2,3]) //window.applayfun2.apply(this,[1,2,3])
    
    applayfun2.apply(applayObj1,[1,2,3]) //window.applayfun2.apply(applayObj1,[1,2,3])

	(3)bind
	
	var title='全局title'
    var applayObj1={
      name:'张三'
    }
    
	var bindObj={
      title:'改变this',
      bindFun(){
        console.log(this)
      }
	}
	
	bindObj.bindFun()
	
	var aa=bindObj.bindFun
	
	aa()
	
	aa.bind(applayObj1)()

4.new 绑定

new出来的对象有以下新特性:

(1)创建一个新对象。
(2)把这个新对象的__proto__属性指向 原函数的prototype属性。(即继承原函数的原型)
(3)将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象)
(4)返回新对象。(底层运行机制return返回一个新对象)
   var blogA='123'
   function blog(){
   	this.blogA='456'
   	this.blogFn=function(){
   		console.log(this.blogA)
   	}
   }
   var newblogObj=new blog() 

   newblogObj.blogFn()
   
   console.log(newblogObj)

三、箭头函数的this绑定

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

    var a=12
	function foo(){	
		this.a=13
	    return ()=>{
	      console.log(this.a)
	    }
	}
    let newFoo=new foo()   
	newFoo() 
	

	var b='666'    
	function foo2(){
        console.log(this)
	    return ()=>{
	        console.log(this.b)
	    }
	}    
	var baz=foo2()
	baz();  

(2)箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域

  function Timer() {
      this.s1 = 0;
      this.s2 = 0;
      
      console.log(this)
      
      // 箭头函数
      setInterval(() => this.s1++, 1000); //箭头函数没有this,它的this来自绑定时所在的作用域 即外部代码块的this
      
      
      // 普通函数
      setInterval(function () { 
        this.s2++; //this为window
      }, 1000);
      
      
    }

	var timer = new Timer();
	
	setTimeout(() => console.log('s1: ', timer.s1), 3100)
	
	setTimeout(() => console.log('s2: ', timer.s2), 3100)
(3). 箭头函数this不可修改
	var obj = {
      b : 999
   }
  var b='666'    
  function foo2(){
      console.log(this)
      return ()=>{
        console.log(this.b)
      }
  }    
  var baz=foo2()
  
  baz();  
  
  baz.call(obj)
  

四、this指向与继承

//示例
		function Parent (name,sex){
			this.name = name;
			this.sex  = sex;
		}

		//添加原型方法
		Parent.prototype.show = function(){
		
			console.log("姓名:" + this.name + "性别" + this.sex)
    
		}
		
		//声明函数继承 Parent的函数 并添加自己的函数
		 function Worker(name,sex,job){
		 
            //通过call方法改变Parent的this指向
            console.log(this)
            Parent.call(this,name,sex)
            this.job = job;
            
		 }

		//此时wk里既有Parent的函数属性 又有了Worker函数的属性
		 Worker.prototype=Parent.prototype
		 
		 var wk = new Worker("小明","男","程序员")
		 
		 console.log(wk.name);
		 
		 console.log(wk.sex);
		 
		 console.log(wk.job);
		 
		 wk.show()