理解js中的this,如果有错误欢迎纠正

有这么一段代码;

var x = 10;

//创建一个对象
var obj = {
    x: 20,
    f: function () {
        console.log(this.x);
        var that = this;
        var foo = function(){
            console.log(that.x);
        }
        foo();
    }
};
obj.f();

首先要讲清楚两个基本概念.
1.在js中一切都是对象,函数也是对象,既然是对象那就有方法。对于函数对象来说,有一个call()的方法,可以吧
2.js中变量的值,变量的值有基本类型值和引用类型值。基本类型值,像数据字符串之类的都是基本类型值。上面说过了既然在js中一切都是对象,变量也是对象,所以也有属性和方法。比如这样 var name="huangweidong";这个时候如果给它一个属性再给个值,name.age="shamate"。纵然不会出错,但是这句会被浏览器pass掉。由于js不能访问并对内存直接操作,而是通过引用。我是这么理解引用的,引用就是js和内存之间的桥梁(欢迎大神纠正错误)。变量其实就是一个有标识符或者id身份的字符串,当我们创建了一个新对象实例时(这时这个对象就会出现并保存在内存堆中)并把它保存在变量中时,变量中保存是什么不是对象的原型(保存在内存中的对象),保存的是引用也就是指针,这个指针指向内存中对象原型。所以当我们把对象复制到其他变量中时,复制的是引用也就是指针,而内存中的对象不被复制。但是基本类型值就不同了,是可以被复制的。

this不就是指向对象嘛,它的值也是一个指针,当把this复制给that时,复制的是引用也就是指针。

console.log(this.x) 要找到x就要从方法所处的对象的上下文去找,这儿我有个问题,当把对象objx属性删了之后,为什么控制台显示的是undefined,不应该是继续往上找吗。*

阅读 4.9k
8 个回答
var x=10;

//创建一个对象
var obj={
    var x=20,
    f:function (){
        console.log(this.x);
        var that=this;
        var foo=function(){
        console.log(that.x);}
        foo ();
    }
};
obj.f();

1)上述代码在语法是有错误的,应该为

var x=10;
//创建一个对象
var obj={
    x:20,
    f:function (){
        console.log(this.x);
        var that=this;
        var foo=function(){
            console.log(that.x);
        }
        foo ();
    }
};
obj.f();

2)当obj.f()语句执行时,this为obj这个对象,这个对象上有属性x,故其console.log(this.x)输出为20,
内部的foo函数执行时,因为之前that已经通过that=this赋值语句指向了obj对象,因为闭包的关系,foo函数依旧能够访问到that变量,所以console.log(that.x)
也是20
3)在闭包环境下,this及arguments是不会到所处函数的外层函数寻找的
4)当obj的x属性被删除,也就是通过delete obj.x语句删除后再执行obj.f(),此时this还是obj,其上的x属性已经不存在了,所以其输出为undefined

题主的理解大概是最危险的那种(对了表面的80%,错了核心的20%)

1.在js中一切都是对象,函数也是对象,既然是对象那就有方法。对于函数对象来说,有一个call()的方法

js中并非一切都是是对象, 原始值就是原始值,不是对象(只不过装箱机制让它看上去有点像对象)

js其实没有方法的概念,尤其是理解核心体系的时候,千万不要用方法这个概念来套JS。方法是基于类OO语言的概念(类-接口-方法),这些概念在JS里都没有,都只能模拟。
平常说JS方法,大概是指“某个对象的某个类型是函数的属性”

js中变量的值,变量的值有基本类型值和引用类型值。基本类型值,像数据字符串之类的都是基本类型值。上面说过了既然在js中一切都是对象,变量也是对象,所以也有属性和方法。比如这样 var name="huangweidong";这个时候如果给它一个属性再给个值,name.age="shamate"。纵然不会出错,但是这句会被浏览器pass掉

也是对一半错一半,JS值区分原始值(说基本值也对,基本类型值也能理解)和引用值(对象),但原始值从来不是对象。 当原始值被点运算求属性值的时候,会触发自动装箱机制,被自动包装成对应的对象。name.age等价于(new String(name)).age,给它赋值不是不出错,而是就能正常运行完,但运行完以后那个自动装箱出来的String对象就被释放掉了

console.log(this.x) 要找到x就要从方法所处的对象的上下文去找,这儿我有个问题,当把对象obj的x属性删了之后,为什么控制台显示的是undefined,不应该是继续往上找吗

题主可能是把“原型链”和“闭包”搞混了,它们确实都“向上找”,但是完全不同的两个机制。原型链影响点运算(查找对象的属性),沿对象的原型链(__proto__)往上找。闭包影响查找不在当前闭包中声明的变量,沿lexical scope查找,也就是按照代码文面的包含关系往上找

//嗯,想起来scope好像就是作用域,那lexical scope应该就是“词法作用域”

因为var x;声明的是全局对象的一个属性,全局对象不在原型链的查找范围内。

此时,this指的就是obj对象(已经确定了,就不会变心了),找属性肯定也是在obj上找其对应的x属性啊。x不存在,所以undefined咯。

因为,你的调用方式是obj.f();,导致只会在obj的这个上下文中找

你这样写不报错吗?

var obj = {
    var x = 20,
    f: function() {
        ... 
    }
}

在上下文往外层作用域查找的是变量,这个东西叫做冒泡机制。而不是this的指向.

  1. {a:1,b:function(){},c:"字符串"} 对象里面都应该是这种关键字,冒号,值的形式。不应该出现赋值语句。所以那个语法错误了。值可以是数字、字符串、函数等等。

  2. this指代调用这个函数的对象。也就是obj。如果obj.func(),在func这一层有this,this就是指func。如果再有一层函数,叫func2,this就指代调用func2的对象了。用that是为了在func2里还能调用func1的值。比如:

var obj={
    x:13;
    func:function(){
        var that=this;
        alert(that.x);//13
        alert(this.x);//13(此时this和that都代指obj)
        $.post(
            'url',
            {name:123},
            function(r){
                alert(that.x);//that一定是obj,所以就相当于取到了obj.x,所以值是13
                alert(this.x);//这里this代指的不管是谁,肯定不是obj了,所以取不到obj.x,值不是13。
            }
        );
    }
}
obj.func();

猜想,题主的疑惑在这里吧:

var x = 10;//定义全局作用域内是x
function foo() {
    var x = 20;//定义函数foo作用域内的x
    function f() {
        console.log(x);
    }
    return f();
}
foo();//20    

当你把var x = 20;删除,输出结果就变成了10。
console.log(x)首先会在f函数内寻找x的值,如果没有找到就在foo函数内找,还没找到,就到全局作用域内找。当我们谈到执行上下文的时候一般是在讲作用域的问题,作用域分为全局作用域和函数作用域,寻找某一个变量时,在函数作用域内没找到,就会沿着作用域链到全局作用域内找。
我想正是这一块的知识点导致了题主在obj对象内写出了var x = 20;的错误语句。

obj.f()讲的是函数调用的问题,牵扯到this的指向,console.log(this.x)中的this指向obj,此语句表示输出对象obj的x值,obj有x则输出具体值,没有就undefined了。

所以,我感觉题主可能是在学习这两个知识点的时候把它俩弄混了一点点……其他知识点像函数调用方式、this指向等感觉题主掌握的应该不错了,我就不在这多废话了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏