粗略认识原型
原型出现的需求起因
构造器创建对象的时候, 实际上会有成员重复
如果使用 构造器 this.方法名 = function .... 方式创建对象. 那么每一个对象
对应的方法就会重复.
解决办法就是让这个方法( 函数 )共享
-> 将函数写到外面, 那么 Person 在初始化对象的时候就不会再创建一个函数了.
只需要将 外面的函数引用 交给对象即可.
缺点: 一个对象可能有 n 多方法. 如果将所有的东西 都放到外面, 与其他库
冲突的几率就会变大. 所以不宜采取该方法.
-> 将所有的方法( 函数 )都绑定到一个对象中.
-> js 原生就支持解决该问题的办法
每一个函数都有 一个属性 prototype
该属性指向一对象. 每一个函数的该对象都是存在.
(重点) 每一个由该函数作为构造器创建的对象, 都会默认连接到该对象上.
如果访问对象的方法, 而对象中没有定义, 就会在这个 构造函数.prototype
表示的对象中去找.
-> prototype 就是原型之意
-> 访问
使用构造函数, 就使用 prototype 属性访问原型
使用实例对象, 就使用 非标准的 __proto__ 属性访问原型
function SlDog(name,age) {
this.name = name
this.age = age
}
SlDog.prototype.sayHi = function () {
console.log('今晚月色真美!');
}
var zs = new SlDog('zs',18)
var ls = new SlDog('ls',20)
console.log(zs.sayHi());
console.log(SlDog.prototype == zs.__proto__);
console.log(zs.__proto__.constructor);
console.log(zs.__proto__.__proto__);
// 访问
// 使用构造函数, 就使用 prototype 属性访问原型
// 使用实例对象, 就使用 非标准的 __proto__ 属性访问原型
constructor构造器
constructor 属性返回对创建此对象的数组函数的引用。
function Person(name,age) {
this.name = name
this.age = age
}
//字面量声明了一个新的原型对象,指向自己(object)
Person.prototype = {
//让构造器指向Person
constructor : Person,
sing : function () {
console.log('哈哈');
}
}
var zs = new Person('zs',18)
var obj = {
name : 'zs'
}
console.log(obj.constructor);
继承
原型与实例对象
在 js 中, 方法定义在原型对象中, 而属性定义在实例对象中
调用方法的时候, 实例对象本身是没有该成员的, 但是依旧可以调用
该方法, 好像这个方法就是该实例对象的一样. 因此, 我们称该实例对象
继承自 原型对象
任何一个实例, 都是继承自其原型对象的. 即原型式继承.
var obj = {
name : 'zs',
age : 18
}
function fn() {}
fn.prototype = obj
console.log(fn);
var zs = new fn()
console.log(zs.name)
原型链
由于链越深, 属性搜索越需要性能. 所以一般少用深层次的链式结构继承一般使用时, 链结构只有 3 级. 一般都是使用混入, 在原型上加成员
属性访问原则( 重点 )
- 对象在调用方法或访问属性的时候, 首先在当前对象中查询. 如果有该成员使用并停止查找.
- 如果没有该成员就在其原型对象中查找. 如果有该成员即使用, 并停止查找.
- 如果还没有就到 该对象的 原型对象 的 原型对象中查找.
…- 最后会查到 Object.prototype 上. 如果还没有即 返回 undefined.
function Person(name, age) {
this.name = name
this.age = age
}
var zs = new Person('zs',18)
console.log(zs.__proto__);
console.log(Person.prototype);
console.log(zs.__proto__ == Person.prototype);
console.log(zs.constructor);
console.log(Person.constructor);
console.log(zs.__proto__.__proto__);
console.log(zs.__proto__.__proto__.__proto__);
og(Person.constructor);
console.log(zs.proto.proto);
console.log(zs.proto.proto.proto);