Appearance
this 指针/闭包/作用域
原型和原型连
原型
原型就是prototype只有函数才有,在javascript里面的对象除了null都有prototype属性,函数实例的__proto__指向的是其构造函数的prototype
js
function Person() {}
const p = new Person()
console.log(p.__proto__ === Person.prototype) // true实例对象的constructor指向的是构造函数
js
function Person() {}
const p = new Person()
console.log(p.constructor === Person) // true
__proto__
绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在于 Person.prototype 中,实际上,它是来自于 Object.prototype ,与其说是一个属性,不如说是一个 getter/setter,当使用 obj.__proto__ 时,可以理解成返回了 Object.getPrototypeOf(obj)。
原型链
在访问一个对象的属性的时候js会先去查询对象本身的属性如果没有就会沿着对象的__proto__去查询其构造函数的prototype是否含有这个属性,一直查询到Object的__proto__为null为止,这个__proto__和prototype组成的链接就叫做原型链 
继承
关于继承,前面提到“每一个对象都会从原型‘继承’属性”,实际上,继承是一个十分具有迷惑性的说法,引用《你不知道的JavaScript》中的话,就是:
继承意味着复制操作,然而 JavaScript 默认并不会复制对象的属性,相反,JavaScript 只是在两个对象之间创建一个关联,这样,一个对象就可以通过委托访问另一个对象的属性和函数,所以与其叫继承,委托的说法反而更准确些。
作用域
支持定义变量和寻址 javascript为静态作用域,在定义的时候就确定了
js
var value = 1
function foo() {
console.log(value)
}
function bar() {
var value = 2
foo()
}
bar() // 1静态作用域的特点就是在函数在定义的时候访问到的变量就已经被确定了 而引用《JavaScript权威指南》的回答就是:
JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效。
执行上下文
- 变量对象
- 作用域链
- this
顺序执行
JavaScript 引擎并非一行一行地分析和执行程序,而是一段一段地分析执行。当执行一段代码的时候,会进行一个“准备工作”
js
a(); // a
function a() {
console.log('a')
}
b() // b is not a function
var b = function() {
console.log('b')
}这里有个变量提升的问题,就是js在运行之前会把声明的变量提升到执行之前值为undefined,函数a就被提升到顶部了,而变量b被提升了但是在被赋值之前就被调用了导致报错
闭包
能访问自由变量的函数 自由变量:既不是入参也不是函数的局部变量