JS 特性汇总

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的内容了。


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();
相关文章
相关标签/搜索