typeof null 为 ”object” 解释
- 不一样的对象在底层都表示为二进制,在JavaScript中二进制前三位都为0的话会被判断为object类型,null 的二进制表示都是0,天然前三位都是0,因此执行 typeof null 时,会返回 ”object”。
传统编程语言编译的三个步骤
- 分词/词法分析
- 解析/语法分析
- 代码生成
变量的赋值操做
- 编译阶段 -- 首次编译器会在当前做用域中声明一个变量(变量提高),若是以前没用声明过。
- 运行阶段 -- 运行时引擎会在做用中查找该变量,若是可以找到就会对它赋值(LHS查询。
做用域
- 做用域是一套规则,用于肯定在何处以及如何查找变量。
- 若是查找的目的是对变量赋值,那么就会使用 LHS 查询。
- 若是查找的目的是获取变量的值,那么就会使用 RHS 查询。
- 不管函数在哪里被调用,也不管它如何被调用,它的词法做用域都只由函数被声明时所处的位置决定。
闭包
- 当函数能够记住并访问所在的词法做用域,即便函数是在当前词法做用域以外执行,这时就产生了闭包。
this
- this 在任何状况下都不指向函数的词法做用域。
- 在 JavaScript 中做用域确实和对象相似,可见的标识符都是它的属性。
- 可是做用域“对象”没法经过 JavaScript 代码访问,它存在 JavaScript 引擎的内部。
- this 是在运行时进行绑定的,并非在编写时绑定,它的上下文取决于函数调 用时的各类条件。
- this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
- 当一个函数被调用时,会建立一个活动记录(有时也称为执行上下文)。
- 这个记录会包含函数在哪里被调用(调用栈),函数的调用方法,传入的参数等信息。this 就是记录其中的一个属性,会在函数执行的过程当中用到。
- this 其实是在函数被调用时发生的绑定,它指向什么彻底取决于函数在哪里被调用。
- 调用栈 — 就是为了到达当前执行位置所调用到的所用函数。
bind()
- 会返回一个硬编码的新函数,它会把参数设置为 this 的上下文并调用原始函数。
new 操做符
使用 new 来调用函数时,会自动执行下面的操做:javascript
- 建立一个新的空对象;
- 这个对象会被执行[[原型]]链接;
- 这个新对象会绑定到函数调用的 this;
- 若是函数没用返回其余对象,那么 new 表达式中的函数调用会自动返回这个新对象。
判断 this
能够根据下面的顺序来进行判断:java
-
函数是否在 new 中调用(new绑定)若是是的话,this 是绑定的是新建立的对象。web
var bar = new foo();
-
函数是不是经过 call apply (显示绑定)或者硬绑定调用,若是是的话,this绑定的是指定的对象。编程
var bar = foo.call(obj2);
-
函数是否在某个上下文对象中调用(隐式调用),若是是的话,this绑定的是那个上下文对象。数组
var bar = obj.foo();
-
若果都不是的话,使用默认绑定,若是在严格模式下,就绑定到 undefined,不然绑定到全局对象上。微信
var bar = foo();
ES6 新增可计算属性名
var prefix = "foo";
var myObject = {
[prefix + "bar"]: "hello",
[prefix + "baz"]: "world"
}
myObject["foobar"]; // hello
myObject["foobaz"]; // world
in / hasOwnProperty() -- 判断某个对象是否存在某个属性
- in 操做符会检查属性是否在对象及其 [[Prototype]] 原型链中。
- hasOwnProperty() 只会检查属性是否在 myObject 对象中,不会检查 [[Prototype]] 链。
forEach() / every() / sone() -- 历数组的值
- forEach() 会遍历数组中的全部值并忽略回调函数的返回值(忽略返回值)。
- every() 方法测试数组的全部元素是否都经过了指定函数的测试(返回值是false终止)。
- some() 方法测试是否至少有一个元素经过由提供的函数实现的测试(返回值是true终止)。
for...in -- 遍历数组下标/对象可枚举属性
for...of -- 遍历可迭代对象的值
- 在可迭代对象上(包括 Array,Map,Set,String,TypedArray,arguments
对象等)上建立一个迭代循环,调用自定义迭代钩子自定义的 @@iterator 对象 ,并为每一个不一样属性的值执行语句。
var randoms = {
[Symbol.iterator]: function() {
return {
next: function() {
return {
value: Math.random()
};
}
};
}
};
var randoms_pool = [];
for (var n of randoms) {
randoms_pool.push( n );
// 防止无限运行!
if (randoms_pool.length === 100) break;
}
类的继承和多态
- 多态并不表示子类和父类有关联,子类获得的只是父类的一份副本,类的继承其实就是复制。
属性的设置和屏蔽
var myObject = {};
myObject.foo = "bar";
- 若是 myObject 对象中包含名为 foo 的普通数据访问属性,这条赋值语句只会修改已有的属性值。
- 若是 foo 不是直接存在于 myObject 中,[[Prototype]] 链就会被遍历,相似 [[Get]] 操做。
- 若是原型链上找不到 foo,foo 就会被直接添加到 myObject 上。
- 然而,若是 foo 存在于原型链上层,赋值语句 myObject.foo = "bar" 的行为就会有些不一样 (并且可能很出人意料)。
- 若是属性名 foo 既出如今 myObject 中也出如今 myObject 的 [[Prototype]] 链上层,那 么就会发生屏蔽。
- myObject 中包含的 foo 属性会屏蔽原型链上层的全部 foo 属性,由于 myObject.foo 老是会选择原型链中最底层的
foo 属性。
转载请注明出处,若是想要了解更多,请搜索微信公众号:webinfoq。闭包