this的指向和用法

this是什么?
this就是一个作用域,他的最外层是指向的Window, 他有一个基本的规则,就是谁调用,那么this就指向谁.

作为前端开发者来说,this是我们最常用到的一个东西了,但是this是什么呢,其实它是每个函数的 this 是在调用时被绑定的,完全取决于函数的调用位置(也就是函数的调用方法),让我们看一看下面的例子吧

function foo() {
	  alert(this.a);
}
var a = 2;
foo();  // 2

因为这里有一个默认的指向,就是从全局里面去拿,如果在严格模式下,那么得到的结果就是

function foo() {
	"use strict";
	console.log( this.a );
}
var a = 2;
foo(); 	// TypeError: this is undefined

下面有四种改变this指向的方法
一. 显示绑定 call 和 apply 方法

function foo () {
	alert(this.a);
}

var obj = {
	a: "aaa"
};

foo.call(obj);  // 结果是 => "aaa"
foo.apply(obj);  // 结果是 => "aaa"

二.硬绑定方法 bind()

function foo () {
	alert(this.a);
}

var obj = {
	a: "aaa"
};

var bar = foo.bind(obj);
bar();      //结果是 => "aaa" 因为bind() 和call apply 不同,它不是立即执行函数,所以需要调用执行      

三. 隐式绑定

function foo () {
	alert(this.a);
}

var obj = {
	a: "aaa",
	foo: foo
};

obj.foo();    // 结果是 => "aaa"

四. new 函数绑定

function foo (a) {
	this.a = a;
}

var foo = new foo("aaa");
alert(foo.a);   // 结果是 => "aaa"

既然这四种绑定已经说完了,那么他们的先后顺序是怎么样的呢

// 隐式绑定 和 显示绑定比较

function foo() {
	console.log( this.a );
}
var obj1 = {
	a: 2,
	foo: foo
};
var obj2 = {
	a: 3,
	foo: foo
};
obj1.foo(); // 2
obj2.foo(); // 3
obj1.foo.call( obj2 ); // 3
obj2.foo.call( obj1 ); // 2

结果是 显示绑定 => 隐式绑定

// 隐式绑定 和 new绑定呢

现在我们需要搞清楚 new 绑定和隐式绑定的优先级谁高谁低:
function foo(something) {
	this.a = something;
}
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 );
console.log( obj1.a );			 // 2
console.log( bar.a );			 // 4

结果是 new的绑定优先级  =>显示绑定  => 隐藏绑定

说了 这么多 我们来看一下 下面的一些例子吧

var name = "张三";
function aaa () {
	var name = "李四";
	this.getName = function () {
		alert(this.name);
		return this.name;
	}
}

var aaa = new aaa();  // 注意, 这里是new 关键字 而不是普通的函数了哦
aaa.getName();   // 这个结果是什么 你知道吗?

好了 我不卖关子了 结果是 => undefinend what? 为什么是undefinend ,在new 实例的时候,根本没有把 this.name = xxx 赋值, 所以this.name 就没法拿到,里面就根本没有,它当然就是undefinend 了

var name = "张三";
function aaa (name) {
	this.name = name;
	this.getName = function () {
		alert(this.name);
		return this.name;
	}
}

var aaa = new aaa("李四");
aaa.getName();    // 现在的结果就是  => "李四"
var name = "张三";
function aaa () {
	var name = "李四";
	bbb();
}

function bbb() {
	alert(this.name);
}

aaa();   // 结果是什么呢?  没错 ,结果是我们的 => "张三" ,因为他并没有涉及到 上面的任何一种改变作用域的方法

既然 提到这里 那么请看一下 下面的这个例子

var name = "张三";

function getName () {
	alert(this.name);      // 结果是  => "张三"
	var name = "李四";
	alert(this.name);      // 结果是 =>  "张三"
}
getName ();                 // 结果 为什么都是张三 你应该很清楚了,因为他们没有this的改动,就默认绑定,去拿全局的name

我们来说一下,没有 this呢,下面的这情况

var name = "张三";
function getName () {
	alert(name);      // undefined
	var name = "李四";
	alert(name);      // "李四"
}
getName ();         // 为什么会这样子呢, 这就涉及到了函数的声明了,函数内局部定义的变量是大于全局定义的变量的,
所以在函数内,程序从上到下执行,alert()在定义的变量前面,所以它不认识 所以就报出来 undefiend 未定义, 这是一个 以前没遇到过的一个小小的坑

箭头函数的作用域,始终是在函数定义的时候决定的

let obj = {
  run: function () {
	return ()=>{
		console.log(this);
   }
  }
}


console.log(obj.run()());

在这里插入图片描述

在这里插入图片描述
箭头函数和普通函数的主要区别在于语法简洁性、‌this指向、‌是否适用于构造函数以及是否具有arguments对象。‌

语法简洁性:‌箭头函数使用箭头(=>)来定义函数,‌语法更加简洁,‌省略了function关键字和大括号。‌例如,‌(x) => x * 2是一个简单的箭头函数表示的函数表达式,‌相当于普通函数function(x) { return x * 2; }。‌箭头函数在只有一个参数的情况下,‌还可以省略括号12。‌

this指向:‌箭头函数没有自己的this绑定,‌它会继承外层作用域的this值。‌而普通函数的this值是根据调用时的上下文决定的1。‌

是否适用于构造函数:‌箭头函数是匿名函数,‌简化了函数定义,‌但不可以当做构造函数。‌这是因为构造函数是通过new关键字来生成对象实例的,‌而箭头函数没有自己的this,‌因此不适用于作为构造函数3。‌

是否具有arguments对象:‌箭头函数没有arguments对象,‌但是可以调用外围的arguments。‌普通函数有arguments对象,‌可以访问函数的参数列表23。‌

综上所述,‌箭头函数在语法上更加简洁,‌但它们在this指向、‌是否可用作构造函数以及是否具有arguments对象等方面与普通函数存在明显的区别。‌
箭头函数是没有原型跟arguments

好了,讲了这么多,相信你也应该对this的指向有所了解了,如果有什么问题,欢迎下面评论指出,一起进步,哈哈哈.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值