有这么一段代码;
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
就要从方法所处的对象的上下文去找,这儿我有个问题,当把对象obj
的x
属性删了之后,为什么控制台显示的是undefined
,不应该是继续往上找吗。*
1)上述代码在语法是有错误的,应该为
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%)
js中并非一切都是是对象, 原始值就是原始值,不是对象(只不过装箱机制让它看上去有点像对象)
js其实没有方法的概念,尤其是理解核心体系的时候,千万不要用方法这个概念来套JS。方法是基于类OO语言的概念(类-接口-方法),这些概念在JS里都没有,都只能模拟。
平常说JS方法,大概是指“某个对象的某个类型是函数的属性”
也是对一半错一半,JS值区分原始值(说基本值也对,基本类型值也能理解)和引用值(对象),但原始值从来不是对象。 当原始值被点运算求属性值的时候,会触发自动装箱机制,被自动包装成对应的对象。
name.age
等价于(new String(name)).age
,给它赋值不是不出错,而是就能正常运行完,但运行完以后那个自动装箱出来的String
对象就被释放掉了题主可能是把“原型链”和“闭包”搞混了,它们确实都“向上找”,但是完全不同的两个机制。原型链影响点运算(查找对象的属性),沿对象的原型链(
__proto__
)往上找。闭包影响查找不在当前闭包中声明的变量,沿lexical scope查找,也就是按照代码文面的包含关系往上找//嗯,想起来scope好像就是作用域,那lexical scope应该就是“词法作用域”
因为var x;声明的是全局对象的一个属性,全局对象不在原型链的查找范围内。
此时,this指的就是obj对象(已经确定了,就不会变心了),找属性肯定也是在obj上找其对应的x属性啊。x不存在,所以undefined咯。
因为,你的调用方式是obj.f();,导致只会在obj的这个上下文中找
你这样写不报错吗?
在上下文往外层作用域查找的是变量,这个东西叫做冒泡机制。而不是this的指向.
{a:1,b:function(){},c:"字符串"} 对象里面都应该是这种关键字,冒号,值的形式。不应该出现赋值语句。所以那个语法错误了。值可以是数字、字符串、函数等等。
this指代调用这个函数的对象。也就是obj。如果obj.func(),在func这一层有this,this就是指func。如果再有一层函数,叫func2,this就指代调用func2的对象了。用that是为了在func2里还能调用func1的值。比如:
猜想,题主的疑惑在这里吧:
当你把
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指向等感觉题主掌握的应该不错了,我就不在这多废话了。