function Person() { } var person = new Person(); person.name = 'zhangsan'; console.log(person.name) // zhangsan
上边这个例子,咱们经过构造函数建立了一个实例,从这个实例到他的原型到最后得object,他们之间得关系,就造成了一个原型链html
prototype __proto__ 和 constructor
首先上边这个例子里边,咱们声明了一个构造函数,在后再这个构造函数里边有一个prototype的属性。浏览器
注意这个prototype属性,是只有函数才会有属性
Person.prototype.name = 'zhangsan'; var person1 = new Person(); var person2 = new Person(); console.log(person1.name) // zhangsan console.log(person2.name) // zhangsan
首先咱们看到再函数的prototype属性上边咱们定义了一个name属性,而后经过new建立了两个实例,
而后经过调用实例的name属性,也能够拿到构造函数prototype属性上边的name属性,
那么这个prototype究竟是有什么用处呢,函数
这个只有函数才会有的属性,他其实指向了一个对象,而这个对象就是调用了构造函数建立实例的原型
,能够理解成是person1,person2在建立的时候从他们的原型把原型的属性委托给了person1和person2this
这里为何不叫他继承,由于继承的定义是赋值一个如出一辙的实例出来,可是js里边并不会复制
这个__proto__属性是每一个对象实例都会有的一个属性,这个属性也会指向该对象的原型spa
function Person() {} var person1 = new Person(); console.log(person1.__proto__ === Person.prototype); // true
能够粘贴一下代码到浏览器打印一下person1 能够看到__proto__这个属性prototype
constructor这个属性以前我也叫他构造函数,叫习惯了,由于每一个原型上边都会有一个constructor这个属性,指向其相关的构造函数指针
function Person() {} console.log(Person === Person.prototype.constructor); // true
首先在你建立一个实例的时候,你去读取实例上边的属性,他会首先再实例上边去查找,若是找不到,那么就去这个实例的原型上边去找,若是仍是找不到,就会去原型的原型上边去找,直到最后找到Object对象,固然object对象也是有原型的 就是nullcode
记得以前的时候,遇到过这么一个问题就是typeof null的 时候为何是个object,记得当时获得的答案是说null是一个对象的空指针,从如今来看null打印object是有缘由的
那么仍是查找不到的话会怎么样的,不要慌(.゚ー゚), 他会返给你一个undefined(.゚ー゚)htm
最后拉一张图对象
图中蓝色的这个链状的结构的线就是原型链
首先什么叫作做用域
做用域是指程序源代码中定义变量的区域。做用域规定了如何查找变量,也就是肯定当前执行代码对变量的访问权限。
JavaScript 采用词法做用域(lexical scoping),也就是静态做用域。
var value = 1; function foo() { console.log(value); } function bar() { var value = 2; foo(); } bar();
网上拿来的例子,直接说过程
在执行阶段执行foo的时候,直接在foo寻找value ,由于js是静态做用域,因此在foo里边没有找到的时候,直接去上一层找,最后结果是1
var value = 1; function bar() { var value = 2; console.log(value); } bar();
同理这段代码bar里边有value 直接打印2
那么再看一个例子
var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f(); } checkscope();
这个例子会打印出什么,你们能够猜一猜
结果就是local scope
那么为何上边的第一段代码里边一样是在函数里边执行另外一个函数,可是他不会用第一个函数里边的变量呢,
缘由就是js是静态做用域,js执行一个函数的时候分为两个阶段,首先会解析一变,这个时候肯定了词法做用域和this指向,属性声明等,而后才是函数执行阶段
函数的做用域是基于函数建立的位置的,因此第一段代码和下边这段代码的函数做用域是不想同的
说到这里的时候,我在上文中提到了执行上下文和函数执行的过程,以前在我得另外一篇博客里边写道过,有兴趣的能够去看下 js的堆栈队列
以上是我对js原型链和做用域的一些认识,有不足的但愿指正,以前在博客园写的。搬过来的