原型及原型链
每个对象都有一个_propto_(隐式原型),指向创建该对象的函数的proptotype(原型)。
Object.prototype的_proto_指向的是null。
函数也是对象,函数也有_proto_,函数是Function创建的。因此,Object._proto_指向的时Function.prototype。(Object也是一个函数)
既然Function也是一种对象,那么Function._proto_指向的是创建该对象(Function)的函数(Function)的Function.prototype。而Function.prototype._proto_指向的是Object.prototype。以上逻辑可自行分析。
当访问一个对象的属性时,会先从基本属性中找,如果没有,则沿着_proto_这条链向上找,这就是原型链。
执行上下文环境及作用域
执行上下文(或执行上下文环境)在准备阶段会完成以下工作:
1.变量、函数表达式--变量声明,默认赋值为undefined
2.this--赋值
3.函数声明--赋值;
javascript在执行一段代码前,会进行这些准备工作来生成执行上下文,这个代码段其实分三种情况:全局代码、函数体、eval代码。其中eval代码接收的也是一段文本形式的代码,例如:eval('alert(qwe)');函数体时代码段是因为函数在创建时,本质上是new Function(...)得来的,需要传入一个文本形式的参数作为函数体。
全局代码的上下文环境数据内容为:
1.普通变量(包括函数表达式) ---声明
2.函数声明 ---赋值
3.this ---赋值
如果代码段是函数体,则再次基础上附加:
1.参数 ---赋值
2.arguments ---赋值
3.自由变量的取值作用域 ----赋值
要给上下文环境下一个通俗定义:在执行代码前,把将要用到的所有变量都事先拿出来,有的直接赋值了,有的先用undefined占个空。
this指针
1.构造函数
所谓构造函数,就是可以用来new对象的函数。注意,构造函数的第一个字母大写。如果函数作为构造函数使用,那么其中的this代表它即将new出来的对象,例如:function AA(){this.name='wewe'};var aa=new AA();aa();如果直接调用,this则指向windows,例如:AA()。
2.函数作为对象的一个属性
如果函数作为对象的一个属性,且作为对象的一个属性被调用时,this指向该对象,例如:var obj={fax:function(){this.name='dsad'}};obj.fax();
如果函数被赋值到另一个变量中,并没有作为对象的属性被调用,this指向window,例如:var func=obj.fax; func();
3.函数用call或apply调用
当一个函数被call或apply调用时,this指向传入的对象,例如:var obj={name:'wewe',code:'dasda'}; var func=function (){console.log(this)}; func.call(obj);
4.全局&调用普通函数
在全局环境下,this永远指向window。普通函数在调用时,this也指向window,例如:var func=function(){console.log(this)};func();
下面例子中的情况需要注意:
var obj={
name:'sddsd',
func:function(){
function f(){
console(this);//这里this依然指向window
}
f();
}
};
obj.func();
关于this的补充内容
在函数的原型链中,this代表的是当前函数对象的值,例如:function Func(){this.name='name';}; var func=new Func(); Func.prototype.getName=function (){console.log(this.name)}; func.getName();
作用域
javascript中除了全局作用域,只有函数可以创建作用域,因此,在声明变量时,全局代码要在代码前端声明,函数中要在函数体一开始就声明好,且建议用单‘var’的形式声明变量。
作用域有上下级的关系,上下级关系的确定是看函数是在哪个作用域下创建的。而作用域最大的好处就是隔离变量,不同作用域下的同名变量不会有冲突。作用域是在函数定义时就已经确定了,而不是在函数调用时。
作用域是一个抽象的概念,类似于地盘,其中没有变量。要通过作用域对应的执行上下文来获取变量的值。作用域中变量的值是在执行过程中产生并确定的,而作用域则是在函数创建时确定的。如果要查找一个作用域下某个变量的值,需要到该作用域对应的执行上下文环境中寻找。
自由变量需要到创建(非调用)该函数的那个作用域中取,这就是所谓的静态作用域。
作用域链中取自由变量值的过程:
1.在当前作用域下查找,有责获取并结束,无则下一步;
2.若当前作用域为全局作用域,则证明该自由变量未定义,结束;否则继续;
3.将创建该函数的作用域作为当前作用域;
4.跳转到第一步;
使用闭包会增加内容开销(因为自由变量的存在,可能会导致一些存放自由变量的上下文环境无法及时销毁)