在声明定义函数时,函数都会有一个
prototype
属性,这个属性就是一个指针,指向一个对象,而这个对象就是原型对象(简称原型)
经过构造函数建立的实例对象,能够直接访问到构造函数的
prototype
属性上(即原型对象)的属性和方法
对象有__proto__
属性, 属性值指向了当前的原型对象, 原型对象也是对象, 原型对象也有__proto__
属性,原型对象的__proto__
属性值指向了原型对象的原型对象, 这样一环套一环,造成的链式结构叫作原型链
原型链特色:面试
__proto__
)等于构造函数的显示原型(prototype
)f1.__proto__ === Foo.prototype //true
Function
的实例,即函数都是经过new
Function
产生的Foo.__proto__ === Function.prototype //true Date.__proto__ === Function.prototype //true Object.__proto__ === Function.prototype //true
Function
也是new
本身产生的,即Function
的隐式原型等于本身的显示原型Function.__proto__ === Function.prototype //true
new
Object
产生的,即原型对象的隐式原型指向Object的显示原型Foo.prototype.__proto__ === Objecct.prototype //true Function.prototype.__proto__ === Objecct.prototype //true
Object
的原型,是原型链的尽头Object.prototype.__proto__ === null //true
constructor
,该属性指向当前的构造函数Foo.prototype.constructor === Foo //true Object.prototype.constructor === Object //true Function.prototype.constructor === Function //true
注意点:函数
__proto__
属性prototype
属性和__proto__
属性constructor
属性和__proto__
属性简化记忆: 沿着对象的原型链往上找this
注意点: 关键看对象上是否有该属性, 而不在意其值是啥spa
简单记忆: 有就修改, 没有就添加prototype
function Person(name, age){ // ****有形参, 无实参, 形参是undefined***** this.name = name; this.age = age; } Person.prototype.name = "lw"; Object.prototype.gender = "male"; // 变化的点 var p = new Person(); console.log(p); // p实例对象的原型链 // p ==> Person.prototype ==> Object.prototype ==> null; console.log(p.name); // undefined **** console.log(p.age); // undefined **** console.log(p.gender); // male console.log(p.sex); // undefined
function Person(name) { // name ==> undefined if (name) { this.name = name; } } Person.prototype.name = "ls"; Person.prototype.money = 100; var p = new Person(); console.log(p); // p实例对象自身没有name属性 console.log(p.name); // ls undefined console.log(p.money); // 100 100
function A() { } A.prototype.n = 1; var b = new A(); A.prototype = { n:2, m:3 } var c = new A(); console.log(b.n, b.m, c.n, c.m) //1 undefined 2 3
function F() {} Object.prototype.a = function () { console.log('a()') } Function.prototype.b = function () { console.log('b()') } var f = new F(); f.a() //a() f.b() //报错 F.a() //a() F.b() //b()
instanceof
判断复杂数据的具体类型的原理是什么?A intanceof B若是B的显示原型属性指向的对象在A的原型链上,则返回true,不然返回false指针
/* 封装一个instanceof的具体实现 参数: A: 实例对象 B: 构造函数 返回值:true或者false */ function myInstanceof(A, B) { // 判断A的数据类型,若是A是简单数据类型或者null,则直接返回false var styleA = typeof A if((styleA !== 'function' && styleA !== 'object') || styleA === null) { return false } // 判断B构造函数的显示原型是否在A实例对象的隐式原型上 var protoA = A.__proto__ while(protoA !== null) { if(protoA === B.prototype) { return true } protoA = protoA.__proto__ } return false }