关于javascript:函数对象和原型原型链的关系

7次阅读

共计 2321 个字符,预计需要花费 6 分钟才能阅读完成。

prototype

只有函数有 prototype 属性

let a = {}
let b = function () {}
console.log(a.prototype) // undefined
console.log(b.prototype) // {constructor: function(){...} }

其实 Object 是一个全局对象,也是一个构造函数,以及其余根本类型的全局对象也都是构造函数:

function outTypeName(data, type) {let typeName =  Object.prototype.toString.call(data)
    console.log(typeName)
}
outTypeName(Object) //[object Function]
outTypeName(String) // [object Function]
outTypeName(Number) // [object Function]

为什么只有函数有 prototype 属性

JS 通过 new 来生成对象,然而仅靠构造函数,每次生成的对象都不一样。

有时候须要在两个对象之间共享属性,因为 JS 在设计之初没有类的概念,所以 JS 应用函数的 prototype 来解决这部分 须要被共享的属性 ,通过函数的prototype 来模仿类:

当创立一个函数时,JS 会主动为函数增加 prototype 属性,值是一个有 constructor 的对象。

以下是共享属性 prototype 的栗子:

function People(name) {this.name = name}
People.prototype.age = 23 // 岁数
// 创立两个实例
let People1 = new People('OBKoro1')
let People2 = new People('扣肉')
People.prototype.age = 24 // 长大了一岁
console.log(People1.age, People2.age) // 24 24

People1People2 的原型是People.prototype

原型链

__proto__Object.getPrototypeOf(target):对象的原型

__proto__是对象实例和它的构造函数之间建设的链接,它的值是:构造函数的 `prototype。

也就是说:__proto__的值是它所对应的原型对象,是某个函数的prototype

Object.getPrototypeOf(target)全等于__proto__

它是 ES6 的规范,兼容 IE9,支流浏览器也都反对。

不要再应用__proto__:

  • __proto__属性没有写入 ES6 的注释,而是写入了附录。
  • 起因是它实质上是一个外部属性,而 不是一个正式的对外的 API,只是因为浏览器广泛支持,才被退出了 ES6
  • 规范明确规定,只有浏览器必须部署这个属性,其余运行环境不肯定须要部署,而且新的代码最好认为这个属性是不存在的
  • 所以无论从语义的角度,还是从兼容性的角度,都不要应用这个属性,应该应用:Object.getPrototypeOf(target)(读操作)、Object.setPrototypeOf(target)(写操作)、Object.create(target)(生成操作)代替

构造函数是什么

所谓的构造函数,实际上就是通过关键字 new 来调用的函数:

let newObj = new someFn() // 结构调用函数

原型继承就是利用结构调用函数的个性

SubType.prototype = new SuperType();  // 原型继承:SubType 继承 SuperType
SubType.prototype.constructor = SubType // 从新指定 constructor 指向 不便找到构造函数
// 挂载 SuperType 的 this 和 prototype 的属性和办法到 SubType.prototype 上
  • 结构调用的第二点:将新对象的 Object.getPrototypeOf(target) 指向函数的prototype
  • 结构调用的第三点:该函数的 this 会绑定在新创建的对象上。(所以父类 this 申明的属性被所有子类实例共享)
  • 新对象赋值给SubType.prototype

原型链是什么

来看个例子:

function foo() {}
const newObj = new foo() // 结构调用 foo 返回一个新对象
const newObj__proto__ = Object.getPrototypeOf(newObj) // 获取 newObj 的原型对象
newObj__proto__ === foo.prototype // true 验证 newObj 的原型指向 foo
const foo__proto__ = Object.getPrototypeOf(foo.prototype) // 获取 foo.prototype 的原型
foo__proto__ === Object.prototype // true foo.prototype 的原型是 Object.prototype

能够用以下三句话来了解原型链

  1. 每个对象都领有一个原型对象 : newObj 的原型是foo.prototype
  2. 对象的原型可能也是继承其余原型对象的 : foo.prototype 也有它的原型Object.prototype
  3. 一层一层的,以此类推,这种关系就是原型链

原型链的起点: Object.prototype

Object.prototype是原型链的起点,所有对象都是从它继承了办法和属性。

Object.prototype没有原型对象

const proto = Object.getPrototypeOf(Object.prototype) // null
正文完
 0