js语法基础-this指向

this的指向也算是js比较容易迷糊的一个点,有时候很容易搞错了this指向的是谁。
有俩点比较关键的说法
1.this总是执行为当前的执行环境。
2.this的指向取决于函数的调用方式

全局的执行上下文中.

	console.log(this == window); // true
	var b = 20;
	console.log(window.b); //20
	this.add = (a,b) =>{
    
    
		return a+b
	}
	window.add(5,5) //10
	

上面的代码我们可以看出。在全局中var == this. == window.;

函数上下文中。

取决于函数的调用方式。
在全局中直接调用

	function foo(){
    
    
        return this;
    }
    console.log(foo() == window) //true

this还是指向window
绑定到对象上调用call,apply。

	let obj = {
    
    
        name:'lly',
        age:20,
    }
    function gud(){
    
    
        return this.name+':'+this.age
    }
    console.log(gud.call(obj)) //lly:20 
    console.log(gud.apply(obj))  //lly:20

call和apply修改了this的指向,从指向window,变成对象obj
构造函数中使用

	function myobj(name,age){
    
    
        this.name = name;
        this.age = age;
        this.say  = function(){
    
    
            return `我叫${
      
      this.name},今年${
      
      this.age}`
        }
    }
    let lly = new myobj('lly',22);
    console.log(lly.say) //我叫lly,今年22

构造函数中指向的是当前new的对象。
new创建的过程
1.创建一个空对象。
2.把this指向这个空对象。
3.进行属性和方法的赋值
4.返回this。
对象方法中使用

	let obj ={
    
    
        name:'lly',
        age:40,
        says:function(){
    
    
            return this.name+':'+this.age
        }
    }
    console.log(obj.says()) // lly:40

在函数调用的时候会指向当前函数,那如果对象里的函数换成箭头函数以后呢。

	var name = '全局';
    var age=20;
    let obj ={
    
    
        name:'lly',
        age:40,
        says:() =>{
    
    
            return this.name+':'+this.age
        }
    }
    console.log(obj.says()) //全局:20 

会神奇的发现this又指向了全局,这是因为箭头函数本身是没有this的。

Dom节点上使用

	$('.btn').click(function(){
    
    
        console.log(this);
    })
    
    document.getElementById('btn').onclick = function(){
    
    
        console.log(this);
    }
	<button onclick="console.log(this);">点我</button>

this都指向DOM元素节点。
总结
判断this指向,this的指向,是在函数被调用的时候确定的,
可以按照一个顺序来看
判读是否是箭头函数。
判断是否有修改指向的行为,call apply bind
判断所在的执行上下文

-------------------------------- 手动分割 -------------------------------------
看完不知道的js之后,做一下记录把,记录成长的对比。
this的几种绑定规则
1.默认绑定

  function wait(){
    
    
	console.log(this.a);
  }
  var a = 2;
 wait(); // 2

上面的代码中的this指向的就是全局变量a的,默认绑定的就把this绑定到全局对象上,所以指向全局对象。根据之前说的看调用的位置,这个调用的位置就是在全局上下文中调用的,所以通过这个就可以看出来。
有一点需要注意下,严格模式下与 wait()的调用位置无关:
2.隐式绑定

	function add(){
    
    
		console.log(this.a+this.b);
	}
	let objs = {
    
    
		a:1,
		b:2,
		add:add
	}
	objs.add(); //  打印 3

在上面我们可以看到,我们把add这个方法通过引用引用到对象obj的一个属性中,我们在通过objs.add
去调用,会发现this指向了我们的objs上。这就是隐式绑定,
**隐式丢失:**在使用隐式绑定的时候可能会照成隐式绑定的丢失。

	function add(){
    
    
		console.log(this.a);
	}
	let objs = {
    
    
		a:10,
		add:add
	}
	let objd = objs.add;
	objs.add();   // 10
	objd();       // undefined

隐式绑定的到objs上的只是一个引用,当再次使用的时候还是一个引用而已。不会附带this的绑定,会变成默认绑定。所以是undefined;

3.显式绑定(硬绑定)
这个也是我们上面说过的俩个 call和apply这俩个改变this的指向,称之为显示绑定,因为我们看的到这个方法就知道是改变了this的指向了。

	function add(){
    
    
		console.log(this.x+this.y);
	}
	let objs = {
    
    
		x:1,
		y:2
	}
	add.apply(objs) //3

这个上面也有提到过,这就简单说一下。apply修改add的指向到objs上。可惜,显式绑定仍然无法解决我们之前提出的丢失绑定问题。
硬绑定 bind方法

	function add(y){
    
    
		console.log(this.x + y);
	}
	let objs = {
    
    
		x:5
	}
	let bar = add.bind(objs);
	bar(10);   //15

bind(…) 会返回一个硬编码的新函数,它会把参数设置为 this 的上下文并调用原始函数。

4.new绑定
new的过程我想大家可能都知道
中间就有一半修改中this的步骤。

	function foo(a) {
    
     
	 this.a = a;
	} 
	var bar = new foo(2);
	console.log( bar.a ); // 2

使用 new 来调用 foo(…) 时,我们会构造一个新对象并把它绑定到 foo(…) 调用中的 this
上。new 是最后一种可以影响函数调用时 this 绑定行为的方法,我们称之为 new 绑定。

如果要判断一个运行中函数的 this 绑定,就需要找到这个函数的直接调用位置。找到之后
就可以顺序应用下面这四条规则来判断 this 的绑定对象。

  1. 由 new 调用?绑定到新创建的对象。
  2. 由 call 或者 apply(或者 bind)调用?绑定到指定的对象。
  3. 由上下文对象调用?绑定到那个上下文对象。
  4. 默认:在严格模式下绑定到 undefined,否则绑定到全局对象

猜你喜欢

转载自blog.csdn.net/weixin_44655037/article/details/117108059
今日推荐