编译发生在代码执行前几微秒,简单来讲就是js在执行前要进行编译,编译过程发生在代码执行前几微妙,甚至更短。闭包
若是查找的目的是对变量进行赋值,那么就会使用 LHS 查询;若是目的是获取变量的值,就会使用 RHS 查询。app
决定于你在写代码时的块级做用域ide
依赖于词法的静态分析函数
在词法分析阶段,没法知道eval with会对做用域作怎样的修改,此时引擎再也不对做用域进行任何优化优化
区分函数声明和表达式最简单的方法是看 function 关键字出如今声明中的位
置(不只仅是一行代码,而是整个声明中的位置)。若是 function 是声明中
的第一个词,那么就是一个函数声明,不然就是一个函数表达式。this
变量(包括函数在内)的全部声明都会优先执行,只有声明自己会提高,而赋值或其余运行逻辑会留在原位置prototype
这意味着不管做用域中的声明出如今什么地方,都将在代码自己被执行前首先进行处理。
能够将这个过程形象地想象成全部的声明(变量和函数)都会被“移动”到各自做用域的
最顶端,这个过程被称为提高。
声明自己会被提高,而包括函数表达式的赋值在内的赋值操做并不会提高。code
当函数可以记住或访问所在的词法做用域,及时是被做用域外调用,就产生了闭包对象
是在函数运行时绑定的,而非定义时。它的上下文取决于函数调用时的各类条件,和在哪里定义的没有关系,只取决于函数的调用方式。继承
当函数被调用时,会建立一个执行上下文,在这个上下文里包含了函数在哪里没调用(调用栈),调用函数的方法,参数等。this做为执行上下文的一个属性,能够在函数执行的过程当中用到。
默认绑定
即绑定到全局,严格模式下回绑定到undefined。
function foo() { console.log( this.a ); } var a = 2; (function(){ "use strict"; foo(); // 2 })()
隐式绑定
即绑定到最顶层(或最近调用对象)上
function fun() { console.log(this.a) } var obj2 = { a: 3, fun: fun, } var obj1 = { a: 2, obj2: obj2, } obj1.obj2.fun() // 3
new绑定(构造函数)
new发生了什么?
基本类型在须要的时候(好比说获取长度),会被引擎默认转成内置对象,从而进行方法的调用。
基础类型并非继承自内置对象
var strPrimitive = "I am a string"; typeof strPrimitive; // "string" strPrimitive instanceof String; // false var strObject = new String( "I am a string" ); typeof strObject; // "object" strObject instanceof String; // true Object.prototype.toString.call( strObject ); // [object String]
typeof null === Object;
原理是这样的,不一样的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判
断为 object 类型,null 的二进制表示是全 0,天然前三位也是 0,因此执行 typeof 时会返回“object”
getOwnPropertyDescriptor(myObj, 'a') defineProperty Object.defineProperty(myObj, 'a', { value: 2, writable: true, configurable: true, enumerable: true })
var obj = { get a() { return this._a_ }, set a(val) { this._a_ = val * 5 } } obj.a = 10 console.log(obj.a) // 50 var obj2 = {} Object.defineProperty(obj2, 'a', { get: function() { return this._a_ }, set: function(val) { this._a_ = val * 2 } }) obj2.a = 15 console.log(obj2.a) // 30
返回实例对象O的构造函数(的引用)。任何一个prototype对象都有一个constructor属性,指向它的构造函数,每个实例也有一个constructor属性,默认调用prototype对象的constructor属性
例如
function Test() { this.name = 'test' } var test = new Test() console.log(test.constructor === Test) // true
构造函数 constructor 是用于建立和初始化类中建立的一个对象的一种特殊方法.
class Polygon { constructor() { this.name = "Polygon"; } } class Square extends Polygon { constructor() { super(); } } class Rectangle {} Object.setPrototypeOf(Square.prototype, Rectangle.prototype); console.log(Object.getPrototypeOf(Square.prototype) === Polygon.prototype); //false console.log(Object.getPrototypeOf(Square.prototype) === Rectangle.prototype); //true let newInstance = new Square(); console.log(newInstance.name); //Polygon
实例对象__proto__指向生成改对象的构造函数的原型
例如
|function Test() { this.name = 'test' } Test.prototype = { color: 'red' } var test = new Test() console.log(test.__proto__ === Test.prototype) // true console.log(test.__proto__)
var foo = { something: function() { console.log( "Tell me something good..." ); } }; var bar = Object.create( foo ); bar.something(); // Tell me something good... Object.create(..) 会建立一个新对象(bar)并把它关联到咱们指定的对象(foo)
这样 咱们就能够充分发挥 [[Prototype]]
机制的威力(委托)而且避免没必要要的麻烦
(好比使 用 new 的构造函数调用会生成 .prototype 和 .constructor 引用)。
缺点
实例的属性都会指向同一个引用
实现
function Parent() { this.names = [1, 2, 3] } function Child() { } Child.prototype = new Parent() var child1 = new Child() var child2 = new Child() child1.names.push(4) console.log(child1.names) // [1,2, 3,4] console.log(child2.names) // [1,2, 3,4]
实现
function Parent() { this.names = [1, 2, 3] this.getName = function () { console.log(this.name) } } function Child() { Parent.call(this) } var child1 = new Child() var child2 = new Child() child1.names.push(4) console.log(child1.names) console.log(child2.names)
缺点
每一个子实例都会实例化方法一次,内存爆炸
实现
function Parent() { this.names = [1, 2, 3] } Parent.prototype.getName = function () { console.log(this.names) } function Child() { Parent.call(this) } Child.prototype = new Parent() var child1 = new Child() var child2 = new Child() child1.names.push(4) child1.getName() child2.getName()
缺点
实现
function Parent() { this.names = [1, 2, 3] } Parent.prototype.getName = function () { console.log(this.names) } function Child() { Parent.call(this) } Child.prototype = Object.create(Parent.prototype) var child1 = new Child() var child2 = new Child() child1.names.push(4) child1.getName() child2.getName()
优势
属性不会再原型链上重复
js中的继承其实就是在对象间创建关联关系,而行为委托就是创建这种关联关系的纽带。
function Foo(who) { this.me = who; } Foo.prototype.identify = function () { return "I am" + this.me; }; function Bar(who) { Foo.call(this,who); } Bar.prototype = Object.create(Foo.prototype); Bar.prototype.speak = function () { alert("Hello," + this.identify() + '.'); }; var b1 = new Bar("b1"); var b2 = new Bar("b2"); b1.speak(); b2.speak();
Foo = { init:function (who) { this.me = who; }, identify:function () { return "I am" + this.name } }; Bar = Object.create(Foo); Bar.speak = function () { alert("hello," + this.identify() + '.'); }; var b3 = Object.create(Bar); b3.init("b3"); var b4 = Object.create(Bar); b4.init("b4"); b1.speak(); b2.speak();