this是什么?
在JavaScript中,this
是一个特殊的关键字,它代表函数被调用时的上下文(context)。this
的值取决于函数是如何被调用的,而不是它在哪里被定义的。在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定)
this绑定的优先级?
new构造函数 > bind call apply方法 > 对象方法 > 普通函数调用
同时,箭头函数的 this
一旦被绑定,就不会再被任何方式所改变。箭头函数中没有this, 会向上级作用域寻找,这意味着箭头函数内部的this
值与其定义时父级的上下文相同。
如果有多个bind链式调用的话,this也只是指向bind的第一个中对象。
ES5中setTimeout的函数时作为回调函数调用的,是挂载到window上的,所以this是指向window的。
call()、apply()、bind()的区别?
1.参数方面的不同
call()、apply()、bind()的第一个参数都是一样的都是想让this指向的值,主要的区别在后面的参数
call()和bind()的第一个参数后面的参数是一个列表形式,就是正常传参
apply()的第一个参数后面的参数是一个数组,数组的中的元素就是要调用的函数的参数
2.返回值方面的不同
call()和apply()都是调用函数后将被调用的函数的返回值返回
bind()则是返回一个函数,所以可以利用bind()将它的返回值多次调用
3.执行方面的不同
call()、apply()都是直接执行调用他们的函数
bind()只是返回一个函数并不执行该函数,需要再手动执行一下
比如如果想让函数立即执行就选择call()或apply()
如果想要多次调用函数就选择bind()
如果不想用数组的形式传参又想让函数立即行就选择call()
总结
- this的值是多变的,由函数的调用方式决定this的值,函数的调用方式有比较多所以导致this的值多变。
- 即便this的值多变让程序员很难确定,也可以通过call()、apply()、bind()手动更改this的指向。
- bind()的返回值是一个函数,并且不会立即执行。
this指向题目,请作答。
要需要补充一点,不管你的对象嵌套多深,this只会绑定为直接引用该函数的地址属性的对象。
// 题目一
var name = "window";
var person = {
name: "person",
sayName: function () {
console.log(this.name);
}
};
function sayName() {
var sss = person.sayName;
sss();
person.sayName();
(person.sayName)();
(b = person.sayName)();
}
sayName();
//题目二
var name = 'window'
var person1 = {
name: 'person1',
foo1: function () {
console.log(this.name)
},
foo2: () => console.log(this.name),
foo3: function () {
return function () {
console.log(this.name)
}
},
foo4: function () {
return () => {
console.log(this.name)
}
}
}
var person2 = { name: 'person2' }
// 开始题目:
person1.foo1();
person1.foo1.call(person2);
person1.foo2();
person1.foo2.call(person2);
person1.foo3()();
person1.foo3.call(person2)();
person1.foo3().call(person2);
person1.foo4()();
person1.foo4.call(person2)();
person1.foo4().call(person2);
//题目三
var name = 'window'
/*
通过new进行调用会执行如下操作
1.创建一个空的对象
2.将这个空的对象赋值给this
3.执行函数体中代码
4.将这个新的对象默认返回
*/
function Person(name) {
this.name = name
this.foo1 = function () {
console.log(this.name)
},
this.foo2 = () => console.log(this.name),
this.foo3 = function () {
return function () {
console.log(this.name)
}
},
this.foo4 = function () {
return () => {
console.log(this.name)
}
}
}
// person1/person都是对象(实例instance)
var person1 = new Person('person1')
var person2 = new Person('person2')
// 面试题目:
person1.foo1()
person1.foo1.call(person2)
person1.foo2()
person1.foo2.call(person2)
person1.foo3()()
person1.foo3.call(person2)()
person1.foo3().call(person2)
person1.foo4()()
person1.foo4.call(person2)()
person1.foo4().call(person2)
// 题目四
var name = 'window'
function Person(name) {
this.name = name
this.obj = {
name: 'obj',
foo1: function () {
return function () {
console.log(this.name)
}
},
foo2: function () {
return () => {
console.log(this.name)
}
}
}
}
var person1 = new Person('person1')
var person2 = new Person('person2')
person1.obj.foo1()()
person1.obj.foo1.call(person2)()
person1.obj.foo1().call(person2)
person1.obj.foo2()()
person1.obj.foo2.call(person2)()
person1.obj.foo2().call(person2)
//题目五
function Foo(){
getName =function(){ console.log(1);}; //没用this定义,相当于全局作用域声明了一个getName函数
return this;
}
Foo.getName =function(){ console.log(2);};
Foo.prototype.getName =function(){ console.log(3);};
var getName =function(){ console.log(4);};
function getName(){ console.log(5)};
//同时声明相同名称的变量和函数,使用了var会造成变量提升,会被解释为
// function getName() {
// console.log(5);
// }
// var getName; // 变量声明被提升
// getName = function() {
// console.log(4);
// };
Foo.getName(); //2
getName(); //4
Foo().getName(); //1 ??当定义 Foo 函数时,getName 并没有被定义。getName 的定义发生在调用 Foo 函数时。
getName(); //1
new Foo.getName(); //2
new Foo().getName(); //3
new new Foo().getName(); //3
1、审题
考察this指向 原型 重名预编译 构造函数
预编译在最前面(变量提升)
全局预编译 函数声明会覆盖变量声明
然后代码会从上往下按顺序执行
添加函数的属性是静态属性
Foo.prototype会对实例的结果造成影响
重新定义的getName函数
函数中没有关键字声明这个getName
没有这个变量会从父级查找
函数的调用看作一个整体
构造函数创建实例什么情况下有属性?
需要给this去绑定