1 预解析-Hoisting函数
■变量提高oop
变量提高,很简单,就是把变量提高提到函数的top的地方。我么须要说明的是,变量提高 只是提高变量的声明,并不会把赋值也提高上来。this
一般,各种文章和JavaScript相关的书籍都声称:“不论是使用var关键字(在全局上下文)仍是不使用var关键字(在任何地方),均可以声明一个变量”。请记住,这是错误的概念:spa
任什么时候候,变量只能经过使用var关键字才能声明。prototype
上面的赋值语句:code
a = 10;
这仅仅是给全局对象建立了一个新属性(但它不是变量)。“不是变量”并非说它不能被改变,而是指它不符合ECMAScript规范中的变量概念,因此它“不是变量”(它之因此能成为全局对象的属性,彻底是由于VO(globalContext) === global,你们还记得这个吧?)。orm
■函数提高 对象
函数类型 | 提高能否 | 函数名有无 | 局部做用域使用与否 |
函数申明方式 |
YES | 必须有 | YES |
函数表达式方式 |
NO | 无关紧要 | YES |
函数构造器方式 |
NO | NO | NO |
◆函数申明方式(函数调用在函数申明以前,依然能够调用)ip
function myTest(){ foo(); function foo(){ alert("我来自 foo"); } } myTest();
◆函数表达式方式(函数调用在函数表达式以前,不能调用.调用后⇒×TypeError foo is not a function)原型链
function myTest(){ foo(); var foo =function foo(){ alert("我来自 foo"); } } myTest();
◆函数构造器方式(不使用局部做用域)
var y = "global"; function constructFunction() { var y = "local"; //Function()构造函数 //不使用局部做用域 return new Function("return y;"); } function constFunction() { var y = "local"; //函数直接量 var f = function () { //使用局部做用域 return y; }; return f; } //显示 global,由于Function()构造函数返回的函数并不使用局部做用域 alert(constructFunction()()); //显示 lobal,由于函数直接量返回的函数并使用局部做用域 alert(constFunction()());
■函数申明和变量申明的关系和影响
function a(x) { x * 2; } var a; alert(a);
遇到同名的函数声明,VO不会从新定义,因此这时候全局的VO应该是以下这样的:
VO(global) = {
a: 引用了函数声明“a”
}
而执行a的时候,相应地就弹出了函数a的内容了。
2 hasOwnProperty函数
hasOwnProperty是Object.prototype的一个方法,它但是个好东西,他能判断一个对象是否包含自定义属性而不是原型链上的属性,由于hasOwnProperty 是 JavaScript 中惟一一个处理属性可是不查找原型链的函数。
// 修改Object.prototype Object.prototype.bar = 1; var foo = {goo: undefined}; foo.bar; // 1 'bar' in foo; // true foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true
只有 hasOwnProperty 能够给出正确和指望的结果,这在遍历对象的属性时会颇有用。 没有其它方法能够用来排除原型链上的属性,而不是定义在对象自身上的属性。
但有个恶心的地方是:JavaScript 不会保护 hasOwnProperty 被非法占用,所以若是一个对象碰巧存在这个属性,就须要使用外部的 hasOwnProperty 函数来获取正确的结果
var foo = { hasOwnProperty: function() { return false; }, bar: 'Here be dragons' }; foo.hasOwnProperty('bar'); // 老是返回 false // 使用{}对象的 hasOwnProperty,并将其上下为设置为foo {}.hasOwnProperty.call(foo, 'bar'); // true
当检查对象上某个属性是否存在时,hasOwnProperty 是惟一可用的方法。同时在使用 for in loop 遍历对象时,推荐老是使用 hasOwnProperty 方法,这将会避免原型对象扩展带来的干扰,咱们来看一下例子:
// 修改 Object.prototype Object.prototype.bar = 1; var foo = {moo: 2}; for(var i in foo) { console.log(i); // 输出两个属性:bar 和 moo }
咱们没办法改变for in语句的行为,因此想过滤结果就只能使用hasOwnProperty 方法,代码以下:
// foo 变量是上例中的 for(var i in foo) { if (foo.hasOwnProperty(i)) { console.log(i); } }
这个版本的代码是惟一正确的写法。因为咱们使用了 hasOwnProperty,因此此次只输出 moo。若是不使用 hasOwnProperty,则这段代码在原生对象原型(好比 Object.prototype)被扩展时可能会出错。
总结:推荐使用 hasOwnProperty,不要对代码运行的环境作任何假设,不要假设原生对象是否已经被扩展了。
3 this
3.1在全局代码中,this始终是全局对象自己,这样就有可能间接的引用到它了。
3.2在一般的函数调用中,this是由激活上下文代码的调用者来提供的,即调用函数的父上下文(parent context )。this取决于调用函数的方式。
如下是经典案例↓
foo() { alert(.bar); } x = {bar: 10}; y = {bar: 20}; x.test = foo; y.test = foo; x.test(); y.test();