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的指向有所了解了,如果有什么问题,欢迎下面评论指出,一起进步,哈哈哈.