JS 原型、原型链、作用域 - 图1

  1. 构造函数:function Foo ( ) { };
  2. 实例对象:let f1 = new Foo();
  3. 1. 谈到继承时,JavaScript 只有一种结构:对象
  4. 2. 每个函数都有 prototype 属性,除了 Function.prototype.bind(),该属性指向原型。
  5. 3. 凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。

prototype


每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型对象,每一个对象都会从原型”继承”属性。

每个对象都有 proto 属性,但只有函数对象才有 prototype 属性

proto


每一个JavaScript对象(除了 null )都具有的一个属性,叫proto,这个属性会指向了创建该对象的构造函数的原型。

console.log(f1._proto_ === Foo.prototype) // true

constructor

每个原型都有一个 constructor 属性指向关联的构造函数

由于实例对象可以继承原型对象的属性,所以实例对象也拥有constructor属性,同样指向原型对象对应的构造函数。

console.log(Foo.prototype.constructor === Foo);//true
console.log(f1.constructor === Foo);//true
console.log(f1.hasOwnProperty('constructor'));//false

原型链

JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做**proto**的内置属性,用于指向创建它的函数对象的原型对象prototype。以上面的例子为例:

console.log(f1.__proto__  === Foo.prototype)  //true

同样Foo.prototype也有proto属性

console.log(Foo.prototype.__proto__ === Object.prototype)  //true

Object.prototype对象也有proto属性,但它比较特殊,为null

console.log(Object.prototype.__proto__ === null)

我们把这个有proto串起来的直到Object.prototype.proto为null的链叫做原型链。原型链的形成是真正是靠proto 而非prototype

总结

每个函数都有一个prototype属性,它默认指向一个Object空对象(即称为: 原型对象)
原型对象都包含一个属性constructor,是一个指针,指向构造函数本身
实例对象包含一个属性proto,是一个指针,指向该构造函数的原型

作用域和作用域链

(1) 作用域

  1. 程序代码中定义变量的区域,简单说就是变量的可访问范围,在该区域中控制着变量的可见性。
  2. 它是静态的(相对于上下文对象), 在编写代码时就确定了

    (2) 作用域链

  3. 理解

  • 多个上下级关系的作用域形成的链, 它的方向是从内到外
  • 查找变量时就是沿着作用域链来查找的
    作用域链保证了当前执行上下文对符合访问权限的变量的有序访问。
  1. 查找一个变量的查找规则
  • 在当前作用域下的执行上下文中查找对应的属性, 如果有直接返回, 否则进入2
  • 在上一级作用域的执行上下文中查找对应的属性, 如果有直接返回, 否则进入3
  • 再次执行2的相同操作, 直到全局作用域, 如果还找不到就抛出找不到的异常