JS中的this

32 篇文章 4 订阅

对this指向大致的定义

 this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁实际上this的最终指向的是那个调用它的对象

 1.普通函数调用,此时 this 指向 window

例一:

function test(){
    var name = "微光";
    console.log(this.name); //undefined
    console.log(this); //Window
}
test();

上面说过this最终指向的是调用它的对象,这里的函数test实际是被Window对象所点出来的

2.对象方法调用, 此时 this 指向 该方法所属的对象

例二:

var o = {
    name:"微光",
    fn:function(){
        console.log(this.name);  //微光
    }
}
o.fn();

因为我们调用fn这个函数是通过了o.fn()执行,那指向明显就是对象o了

例三:

var o = {
    name:"微光",
    fn:function(){
        console.log(this.user); //微光
    }
}
window.o.fn();

这段代码跟例二几乎是一样,我们先来理解下为啥这里的this为什么不是指向window,如果按照上面的理论,最终this指向的是调用它的对象,

这里先说个而外话,window是js中的全局对象,我们创建的变量实际上是给window添加属性,所以这里可以用window点o对象

我们先不说为啥会不指向window,接下来再看一段代码。

例四:

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //12
        }
    }
}
o.b.fn();

这里同样也是对象o点出来的,但是同样this并没有执行它,可能你会说为啥不是指向对象o?

补充三个知识点:

 1:如果一个函数中有this,但它没有被上一级的对象所调用,那么this指向的就是window

 2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象

 3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

例四可以证明,如果不相信,那么接下来我们继续看几个例子。

例5: 

var o = {
    a:10,
    b:{
        fn:function(){
            console.log(this.a); //undefined
        }
    }
}
o.b.fn();

尽管对象b中没有属性a,这个this指向的也是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西

还有一种比较特殊的情况,例6:

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
var j = o.b.fn;
j();

这里this指向的是window,是不是有些蒙了?其实是因为你没有理解一句话,这句话同样至关重要。

this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的

例6中虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向的是window,这和例子5是不一样的,例子5是直接执行了fn。

构造函数版this:

function Fn(){
    this.user = "追梦子";
}
var a = new Fn();
console.log(a.user); //追梦子

构造函数调用, 此时 this 指向 实例对象,new关键字可以改变this的指向

将这个this指向对象a

为什么我说a是对象,因为用了new关键字就是创建一个对象实例,我们这里用变量a创建了一个Fn的实例(相当于复制了一份Fn到对象a里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象a,那么this指向的自然是对象a

当this碰到return时:

function fn()  
{  
    this.user = '微光';  
    return {};  
}
var a = new fn;  
console.log(a.user); //undefined
function fn()  
{  
    this.user = '微光';  
    return function(){};
}
var a = new fn;  
console.log(a.user); //undefined
function fn()  
{  
    this.user = '微光';  
    return 1;
}
var a = new fn;  
console.log(a.user); //微光
function fn()  
{  
    this.user = '微光';  
    return undefined;
}
var a = new fn;  
console.log(a.user); //微光

如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。

还有一点就是虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊。

function fn()  
{  
    this.user = '微光';  
    return null;
}
var a = new fn;  
console.log(a.user); //微光

 箭头函数中的this:

const o = {
  a() {
    console.log(this)
  },
  b: () => {
    console.log(this)
  }
}

o.a() //o
o.b() //window

const c = o.a //window 复制并没有执行
const d = o.b //window
c()
d() 

当我们使用箭头函数时,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this

面试题一:

var foo = 1;
function bar() {
    foo = 10;
    return;
    function foo() {}
}
bar();
alert(foo);

输出1,考察了变量提升,可以变为

var foo = 1;
function bar(){
	function foo(){};  // 这里在内部定义了 foo 是一个函数
	foo = 10; // 因此这里属于局部变量,不影响到外层的foo
	return foo;
}
bar();
alert(foo) //1
// 在foo=10的时候,foo是有定义的,属于局部变量,影响不到外层的foo。

1、预解析中,变量的提升,只会在当前的作用域中提升,提前到当前作用域的最前面。
2、函数的变量只会提前到函数作用域的最前面,不会出去影响全局的变量。

面试题二:

function bar() {
    return foo;
    foo = 10;
    function foo() {}
    var foo = 11;
}
alert(typeof bar());

输出function,相当于

// 上述代码相当于:
function bar() {
	function foo() { }
	var foo; //函数提升优先级高于变量提升,且不会被同名变量声明时覆盖,但是会被变量赋值后覆盖
	return foo;
	foo = 10;
	foo = 11;
}
alert(typeof bar());

 面试题三:

var x = 3;
var foo = {
    x: 2,
    baz: {
        x: 1,
        bar: function() {
            return this.x;
        }
    }
}
var go = foo.baz.bar; //并没有执行所以最终指向的是window
alert(go());
alert(foo.baz.bar()); //只指向上一级

输出3,1,

 面试题四:

x = 1;
function bar() {
    this.x = 2;
    return x;
}
var foo = new bar(); //new 改变了this指向
alert(foo.x);

输出2

面试题五:

var arr = [];
arr[0]  = 'a';
arr[1]  = 'b';
arr.foo = 'c';
arr.name = "zs"

alert(arr.length); // arr = ["a", "b", foo: "c", name: "zs"]

2,数组的原型是 Object,所以可以像其他类型一样增加属性,但是不影响其固有性质。arr.foo 和 arr.name 不算在 arr.length 中

面试题六:

function foo(){}
delete foo.length;
alert(typeof foo.length);

number,length属性无法被删除

面试题七:

var name="the window";
var object={
  name:"my object",
  getName: function(){
    return this.name;
  }         
}

object.getName(); 
(object.getName)();
(object.getName = object.getName)()

输出

  my object

  my object

  the window

备注:

第一行的代码,this指向的就是object,所以毫无疑问;

第二行代码虽然加上括号,就好像只是在引用一个函数,但this的值得到了维持。因为object.getName和(object.getName)的定义相同。

第三行代码,先执行一条赋值语句,然后再调用赋值后的结果。因为这个赋值表达式的值是函数本身,所以this的值不能得到维持,结果就返回the window.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值