1.先做题看看自己有啥问题---先做再跑哈
第零题
let name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);
}
}
let f=obj.func;
f();
复制代码
第一题
let name="window"
let obj={
name:"zhangsan",
func:function(){
console.log(this.name);
}
}
let f=obj.func;
f();
复制代码
第二题
var name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);
}
}
let f=obj.func;
f();
复制代码
第三题
var name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);
}
}
obj.func();
复制代码
第四题
var name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);
}
}
let f=obj.func;
f.apply(obj);
复制代码
第五题
var name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);
}
}
let f=obj.func;
f.call(obj);
复制代码
第六题
var name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);
}
}
let f=obj.func;
f.bind(obj);
复制代码
第七题
var name1 = 'name';
var obj = {
name1: 'zhansan',
func: function () {
let s = () => console.log(this.name1);
return s;
}
};
let f = obj.func;
let func=f();
func();
复制代码
第八题
var name1 = 'name';
var obj = {
name1: 'zhansan',
func: function () {
let s = () => console.log(this.name1);
return s;
}
};
let f = obj.func();
f();
复制代码
第九题
var name1 = 'name';
var obj = {
name1: 'zhansan',
func: function () {
let s = () => console.log(this.name1);
return s;
}
};
let f = obj.func();
let B={
name:"lisi"
}
f.call(B);
复制代码
第十题
var length = 10;
let fn = () => {
console.log(this.length);
}
var obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]();
},
};
obj.method(fn, 1);
复制代码
2.答案解释
第零题
let name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);//undefined
}
}
let f=obj.func;
f();
复制代码
类中的方法中this的指向由其调用对象决定,本题中最终执行时候是直接调用的,所以指向全局的window对象,那为什么不是输出window呢,哦原来是let声明的(var声明的和函数声明才会变成window的属性)。
第一题
let name="window"
let obj={
name:"zhangsan",
func:function(){
console.log(this.name);//name
}
}
let f=obj.func;
f();
复制代码
这题就是坑人,name
虽然不是关键字也不是保留字,但它是属性,不能作为变量名,类似的有top
,location
,self
,但left
,bottom
却可以,原因是这些变量名是JS的主机变量,永远不能被重新声明,带上链接这就说明在平时变量命名时候要遵循一定的规范呀,要不然这样的错误是真的难以理解。。。
第三题
var name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);//zhangsan
}
}
obj.func();
复制代码
这题就是正常的题目了,不懂得话自己看第零题,如果代码这样改
var name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);//window
}
}
let func=obj.func;
func();
复制代码
那么结果就应该是window了,同第零题解释。
第四题
var name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);//zhangsan
}
}
let f=obj.func;
f.apply(obj);
复制代码
这题就要讲apply了,可以用来改变this的指向,这里原来调用者本来是window但是由于使用了apply并传入调用者obj对象,所以this指向obj。
第五题
var name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);//zhangsan
}
}
let f=obj.func;
f.call(obj);
复制代码
没错,这题的要讲的就是call了,它也是用来改变this的指向,那么问题来了,有两个改变this的api我该用哪个呢?这就涉及到它们的1第二个参数了,由于在调用函数时候,有些函数是需要传入参数的(我这里的函数都是无参函数,所以看起来没区别),当要传参数的时候,二者的区别就出来了。看下面的例子
var name1 = "window"
let obj = {
name1: "zhangsan",
func: function(age, job) {
console.log(`${this.name1}是个${age}岁的${job}`);
}
}
let f = obj.func;
f.call(obj, 18, "切图仔");
复制代码
var name1 = "window"
let obj = {
name1: "zhangsan",
func: function(age, job) {
console.log(`${this.name1}是个${age}岁的${job}`);
}
}
let f = obj.func;
f.apply(obj, [18, "切图仔"]);
复制代码
看到这里相信你已经看出区别了,apply传参的时候传的是按数组传参,call传参的时候是按参数一个一个传。
第六题
var name1="window"
let obj={
name1:"zhangsan",
func:function(){
console.log(this.name1);//都没执行。。。。。
}
}
let f=obj.func;
f.bind(obj);
复制代码
相信你已经知道答案了,没错又忘记bind不会直接调用,而是返回一个函数了吧,和上面两个相似,bind也是用来改变this的指向,但是此时函数不会立即指向,而是返回一个已改变this指向的函数,你需要手动调用一下,至于传递参数它也是一个参数一个参数的传。
第七题
var name1 = 'name';
var obj = {
name1: 'zhansan',
func: function () {
let s = () => console.log(this.name1);//name
return s;
}
};
let f = obj.func;
let func=f();
func();
复制代码
终于ES6中的箭头函数登场了,开始背:箭头函数没有自己的this,箭头函数中的this指向的是定义时的this,而不是执行时的this。-_-可是好像还是和我要的答案不一样,那就是理解错误了?还有的博客说,箭头函数在定义的时候this就确定了。???更加的迷糊了什么鬼。其实箭头函数没有自己的this,其this来源于其定义的时候的执行上下文的this,所以不是一定义就确定,而是要看最近的外层函数的this是什么,箭头的函数就是什么!!!很显然外层函数执行的时候的this是可以改变的,所以并不是说箭头函数在定义的时候this的指向就确定了,这是关键的地方,那么本题也就很好解释了,obj.func赋值给了全局的f后直接调用了,调用的对象就是全局的window,那么箭头函数的this就是window自然输出了全局的name1。让我们在看下一题进行对比。
第八题
var name1 = 'name';
var obj = {
name1: 'zhansan',
func: function () {
let s = () => console.log(this.name1);//zhangsan
return s;
}
};
let f = obj.func();
f();
复制代码
借助上一题的解释,这一题的答案也是显而易见了,箭头函数的外层函数的执行调用者是obj,所以其this指向就是obj对象,那么自然箭头函数的this取决于外层函数的this,所以输出zhansan。
第九题
var name1 = 'name';
var obj = {
name1: 'zhansan',
func: function () {
let s = () => console.log(this.name1);//zhansan
return s;
}
};
let f = obj.func();
let B={
name:"lisi"
}
f.call(B);
复制代码
如果你有认真的做前面的两道题,相信你这题也是可以对的,没错,由于箭头函数的外层函数的调用对象是obj,所以箭头函数的this就确定了,就是指向obj,即使你后来用改变this指向的call,apply,bing等都是步骤效的,要想改变this的指向就要改变func的调用者! 看到这里你是不是对this已经信心满满了呢?来看最后一题
第十题
var length = 10;
let fn = () => {
console.log(this.length);//10 10
}
var obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]();
},
};
obj.method(fn, 1);
复制代码
ee看到length又看到arguments就知道这道题不简单,但是仔细想想this在定义的时候,this就由其定义的外层函数的指向调用者所决定了,这里很明显fn定义在全局,那它外层的指向上下文改不了只能是object,所以答案也就出来了就是:只要调用到fn函数,输出的都是全局的length:10,arguments只是一个幌子。。。。。
总结:
1.全局定义的函数,如果直接调用,this的指向就是window。 2.对象中的方法(普通方法),其this的指向由其调用者决定,谁调用我就指向谁,注意什么是调用!!!!(obj.fn只是获取函数,obj.fn()才是执行调用); 3.普通的函数,可以通过apply,call,bind注意三者的区别,apply传参要将参数放在数组中,bind和call要一个一个传,且bind不会执行改函数,还要手动调用一下。 4.箭头函数没有自己的this,其this的指向由定义时候的最近外层函数的this所决定,所以要改变其this的指向,应该改变它最近外层的函数执行对象! 5.还有就是要注意一些特殊的变量名,这里水太深了。 6.还有对象中的this,严格编译下的。。。。下次一定