JS 特性汇总

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1 预解析-Hoisting

■变量提升

变量提升,很简单,就是把变量提升提到函数的top的地方。我么需要说明的是,变量提升 只是提升变量的声明,并不会把赋值也提升上来

通常,各类文章和JavaScript相关的书籍都声称:“不管是使用var关键字(在全局上下文)还是不使用var关键字(在任何地方),都可以声明一个变量”。请记住,这是错误的概念:

任何时候,变量只能通过使用var关键字才能声明。

上面的赋值语句:

a = 10;

这仅仅是给全局对象创建了一个新属性(但它不是变量)。“不是变量”并不是说它不能被改变,而是指它不符合ECMAScript规范中的变量概念,所以它“不是变量”(它之所以能成为全局对象的属性,完全是因为VO(globalContext) === global,大家还记得这个吧?)。

■函数提升 

函数类型 提升可否 函数名有无 局部作用域使用与否
函数申明方式
YES 必须有 YES
函数表达式方式
NO 可有可无 YES
函数构造器方式
NO NO NO

   ◆函数申明方式(函数调用在函数申明之前,依然可以调用

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();




转载于:https://my.oschina.net/u/2447574/blog/639267

你可能感兴趣的:(JS 特性汇总)