原型和原型链 是js初学者的噩梦 虽然工作过程中用不到 但理解它 对于我们写代码 看源码有很大的提升的!
什么是原型讷?
我们创建每一个函数 都有一个prototype(原型) 属性
这个属性是一个指针 指向一个对象
而这个对象的作用是 存放这个类型创建的所有实例共享的属性和方法
指向这个对象 就是我们所谓的原型对象原型对象的作用?
使用的好处是 可以让所有对象实例共享它所包含的属性和 方法
换句话说 不必在构造函数中定义对象实例的信息 而是将信息直接添加至原型对象上
原型概念
在js中万物皆对象
每一个js"对象"创建的时候 就会与之关联另一个对象 这个对象就是我们所说的原型 每一个对象都会从原型中 继承属性
prototype
在js中 每一个函数都有一个prototype属性 该属性指向函数的原型对象
当用该函数构造出 一些对象之后 这些对象也继承了原型对象上的属性 看代码
function Person(){}
Person.prototype.name = "protoName"
var person1 = new Person()
console.log(Person1.name) //protName
1 注意person1 由于本身上没有name这个属性
2 所以他会去构造函数Person找
3 而person函数本身也没有name属性
4 所以会去Person.prototype上找
也就是去Person的原型上面找 这就是基本的原型链了
图解执行步骤
proto
当调用构造函数创建一个新的实例后 该实例的内部将包含一个内部属性 该属性的指针指向构造函数的原型对象
这个属性就是 proto
每个对象都有一个_proto_属性 它指向该对象的原型 就是说
function Person(){}
var person1 = new Person()
console.log(person1._proto_ === Person.prototype) // true
图解执行的步骤
constructor
每个原型 都有一个constructor (就是说constructor是存在prototype上面的属性) 指向关联的构造函数
function Person(){}
var Person1 = new Person()
console.log(Person.prototype.constructor === Person) //true
console.log(Person.prototype.constructor === Person1.constructor) //true
person1本身没有constructor属性
所以UI沿着 继续向原型链顶端找 去它的构造函数person函数上找 而构造函数的原型上面有constructor属性
就是说 person1没有constructor属性 查找Person的constructor属性 Person没有constructor属性 查找 Person.prototype的constructor属性
如图所示
原型的原型
原型本质也是一个对象 那么对象可以通过new Object构建出来
就是说 原型的_proto_属性指向原型的原型 也就是Object.prototype
function Perrson(){}
var person1 = new Perrson();
console.log(Person.__proto__ === Function.prototype) // true
console.log(Person.prototype.__proto__ === Object.prototype) // true
综上所述 摘自《javascript高级程序设计》
1 回顾构造函数 原型和实例的关系 每一个构造函数都有一个原型对象 原型对象都包含一个指向构造函数的指针
而实例都包含一个指向对象的内部指针
2 那么假如我们让原型对象等于 另一个类型的实例 结果?此时原型对象将包含一个指向另一个原型的指针 相应
的 另一个原型中也包含着一个指向另一个构造函数的指针 假如另一个原型又是另一个类型的实例 那么上述关系依
然成立 如此层层递进 构成了实例于原型的链条 这就是所谓的原型链的基本概念啊
3 是不是 一脸懵逼 哈哈哈
我的理解
就是说
假如函数a的原型是函数b的实例对象
而函数b的原型是函数c的实例对象
函数c的原型是函数d的实例对象
那么a b c d 就会构成一个原型链
此时如果函数a的实例对象需要去找一个属性x 在函数a找不到的时候 就去函数a的原型上找 再找不到就去去函数b
的原型上面找 就是说沿着原型链 一层一层的找
嗯呐 就是这样
构造原型关系的方法
//确定原型链中 出现过的构造函数 结果会返回 true
//instanceof
function Person(){}
var person1 = new Person()
console.log(person1 instanceof Person) //true
console.log(person1 instanceof Object) //true
//因为所有对象的原型都是 Object.prototype 所以也会在原型链上
//isPrototypeOf
//用法和instanceof差不多
function Person(){}
var person1 = new Person()
console.log(Person.prototype.isPrototypeOf(person1)) // true
console.log(Object.prototype.isPrototypeOf(person1)) // true
1 创建一个函数就会为其创建一个prototype属性,指向这个函数的原型对象,原型对象会自动获得constructor属性,指向prototype属性所在函数。 2 当一个对象调用某个方法或者属性的时候,先在自身查找,如果找到就调用,如果没有就顺着__proto__到原型对象中查找,如果还没有就继续去原型的原型中查 3 一直到null,这样形成一条链叫做原型链。如果还没有找到就返回undefined。
portotype 与 proto
显示原型(prototype)
每一个函数在创建后 都会拥有一个名为prototype的属性 这个属性指向函数的原型 (用访问函数的原型对象)
proto隐式原型
js中任意对象都有一个 内置属性prototype
//代码示例 ?
function Test(){
const test = new Test();
}
test._proto_ === Test.prototype; //true
//即构造函数 拥有prototype属性 对象实例 拥有_proto_属性 他们都是用来访问原型对象的
//函数一个特点 它不仅是函数 还是一个对象 所以它也有_proto_属性
demo
//创建对象的构造函数
function Person(){
//通过原型对象来设置一些属性和值
Person.prototype.name ="changDongDong"
Person.prototype.age = 18
Person.prototype.height = 1.88
Person.prototype.sayHellow = function(){
alert(this.name)
}
//创建俩对象实例 并且调用方法
}
var person1 = new Person()
var person2 = new Person()
person1.sayHellow(); //changDongDong
person1.sayHellow(); //changDongDong
> 在上面代码中 没有给实例对象单独设置属性和方法 而是直接设置给了原型对象
> 而原型对象的作用 是可以让所有的对象来共享 这些属性 和方法
> 因此 调用sayHellow()方法时 他们打印出的一样 他们是共享的