《你不知道的javascript》上卷笔记整理,一

函数声明和变量声明都会被提升,但函数声明会被提升到普通变量前,而

var foo = function bar(){};

赋值操作不会被提升。

闭包:

基于词法作用域(作用域是根据名称查找变量的一套规则)书写代码时所产生的必然结果。

ReferenceError同作用域判别失败相关。

TypeError代表作用域判别成功,但结果的操作是不合法的。

不成功的RHS引用会抛出ReferenceError。

不成功的LHR引用会导致自动隐式创建一个全局变量。

展示闭包效果的代码:

function foo(){
   var a =2;
   function bar(){
    console.log(a);
  }    
  return bar;    
}
var baz = foo();//2

闭包使函数可以继续访问定义时的词法作用域。

无论通过何种手段将内部函数传递到所在词法作用域之外,它都会持有对于原始作用域的引用,无论在何处执行这个函数,都会使用闭包。

将函数作为值并到处传递,就可以看到闭包的应用。定时器,事件监听器,ajax,跨窗口通信,web workers或其他的异步(或同步)任务中,只要使用了回调函数,实际上就是使用闭包。

如果不执行外部函数,内部作用域和闭包都无法被创建。

模块模式的条件:

1、必须有外部的封装函数,该函数至少被调用一次。

2、封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域形成闭包,并且可以访问或修改私有的状态。

词法作用域是在定义时确定的,动态作用域是在运行时确定的(判断this)。

this:

foo.call(foo,i);//使用call(...)可确保this指向函数对象foo本身

this在任何情况下都不止像函数的词法作用域。

this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

非严格模式下的默认绑定才能绑定到全局对象。

当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。

显示绑定this的方法:apply(...)、call(...)

工作原理:第一个参数是对象,把这个对象绑定到this,调用函数时指定这个this。

硬绑定:bind()

使用new来调用函数或者说发生构造函数调用时会执行:(new绑定)

1、创建(或构造)一个全新对象;

2、这个对象会被执行原型链接;

3、这个对象会被绑定到函数调用的this;

4、如果函数没有其他对象,那么new表达式中的函数调用会自动返回这个心对象;

判断this的基本方法:

1、new绑定:this指向心创建对象。

2、call()/apply()绑定或硬绑定,指向绑定对象。

3、上下文调用(隐式绑定)this指向上下文对象。

4、以上皆不是,使用默认绑定,严格模式下是undefined,非严格模式为全局对象。

箭头函数不使用this的四种标准规则,而是根据外层(全局或函数)作用域来决定this,箭头函数的绑定无法被修改,它可以像bind()一样确保函数的this被绑定到指定对象上,和(self = this)机制一样。

(尽量避免使用self=this和箭头函数,改用bind(...))

polyfill指挂墙的腻子,polyfill代码主要用于就浏览器的兼容。

js中创建空对象最简单的方法:

Object.creat(null)

与{}很像但不会创建Object.prototype委托。完全不会受到原型链干扰,非常适合存储数据。

null会被判断为对象的原因:不同对象在底层表现为二进制,js中二进制前三位为0会被判断为对象,null二进制全是0,所以执行typeof会返回“object”