自定义构造函数的缺点:
如果在自定义构造函数内,给每一个对象添加相同的方法,每生成一个对象,都会开辟空间存储方法,造成内存浪费
解决方法: 可以通过原型对象解决
1. 将共享的方法添加到原型对象上
2. 构造函数创建出来的对象的对象可以直接访问原想的成员(属性和方法)
首先先来认识一下原型
原型的三角关系:每个函数都有prototype属性,指向原型
原型中有属性constructor指向构造函数
实例中有属性__proto_-指向原型
如下图:
注意点: 不推荐直接通过__proto__修改属性
需要通过构造函数.prototype来修改原型添加成员
原型上添加成员的注意点:
1. 构造函数上添加的成员,实例拿不到
2. 原型上添加的成员实例可以拿到
原型链
一个对象有自己的原型,原型也是一个对象,有它自己的原型,一环扣一环,就形成了一个原型链
由此对于实例来说,自己的属性可以访问,原型上的属性可以访问,原型链上的属性也可以访问
属性搜索原则:
实例去获取属性:自己有就访问自己的,自己没有在原型链上就近查找
对于实例去设置属性,只会对自身进行操作,如果属性存在,就修改值,如果属性不存在,就添加属性,并赋值,不会对原型进行设置
对于Object.prototype的成员的认识
首先Object.prototype是所有对象的老祖宗,是原型链的顶端
所有Object.prototype里面的成员,所有的对象都可以访问
1.hasOwnPrototype
对象.hasOwnPrototype(属性名) 判断属性是否是自己的,而不是原型的
var obj = { name:'zs', age:18 } console.log(obj.hasOwnProperty('name')) //true
2.isPrototypeof
A.isPrototypeof(B) 判断A是否是B的原型
function Person(name,age){ this.name = name, this.age = age } var p = new Person('zs',12) console.log(Person.isPrototypeOf(p))//false
3.tostring方法
Object.prototype.tostring 判断数据类型
Array.prototype.tostring 转字符串(被重写)
4.valueof
5.属性名 in 对象 判断属性是否可以被对象访问,自己的或者原型
Instanceof
A instanceof B 判断A是否是B的实例(或者理解为B.prototype是否在A的原型链上)
function Person(name, age) {
this.name = name;
this.age = age;
}
var p = new Person();
var arr = new Array();
console.log(arr instanceof Array); // true
console.log(arr instanceof Object);//true
如何获取一个对象的类型
Function Person(){}
Var p = new Person()
1.p.constructor // ƒ Person(){}
2.p.__proto__.constructor.name //Person
3.p.constructor.name //Person