一、构造函数弊端
1、构造函数中的实例每调用一次方法,就会在内存中开辟一块空间,造成内存浪费。
// 创建一个构造函数
function Person(name, age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log("大家好,我是"+this.name)
}
}
// 实例化对象
var p1 = new Person('张无忌',22);
var p2 = new Person('赵敏',20);
var p3 = new Person('周芷若',21);
// 函数调用
p1.sayHello();
p2.sayHello();
p3.sayHello();
console.log(p1.sayHello === p2.sayHello, p2.sayHello === p3.sayHello);
//false
//flase
二、原型
1、简单来说
原型有两个,prototype显示原型和__proto__隐式原型。
(1)函数中必然有prototype,除内置对象、浏览器对象、闭包对象。
(2)产生于函数定义时,给函数对象添加prototype属性,显示原型,给原型对象添加constructor属性, 值为函数。
prototypefunction Fn(){}
console.dir(Fn)
var obj ={}
console.log(obj.__proto__===Object.prototype)
console.log(Fn.prototype.__proto__===Object.prototype)
(1)对象中必然有__proto__
(2)产生于实例化对象时,JS引擎自动给实例添加____proto__属性, 值为构造函数的 prototype属性的值。
this.__proto__ = Fn.prototype // this是实例对象
2、总的来说
(1)原型:在构造函数中,有一个属性prototype,它指向了一个对象,这个对象就是原型对象,这个对象的所有属性和方法,都会被构造函数所拥有。
function Person(name, age){
}
console.log(Person.prototype)
// {constructor: ƒ}
// constructor: ƒ Person(name, age)
// __proto__: Object
(1)普通函数调用,prototype没有任何作用,构造函数调用,该类所有实例有隐藏一个属性(proto)指向函数的prototype。(实例的隐式原型指向类的显示原型)
//实例的隐式原型指向构造函数的显示原型
console.log(p1.__proto__ === Person.prototype);
//true
(3)原型就相当于一个公共区域,可以被类和该类的所有实例访问到。
(4)所以我们在定义类时,公共属性定义到构造函数里面,公共的方法定义到构造函数外部的原型对象上。
3、本质
普通object实例
4、优点
(1)资源共享,节省内存
(2)改变原型指向,实现继承
5、缺点
查找数据的时候有的时候不是在自身对象中查找
三、 constructor构造函数
对象原型(proto)和构造函数(prototype)里面都有一个属性叫做constructor。
constructor称为构造函数,因为他指回构造函数本身。
1、记录该对象引用哪个构造函数
console.log(p1.__proto__.constructor);
console.log(Person.prototype.constructor);
/*ƒ Person(name, age){
this.name = name;
this.age = age;
}
ƒ Person(name, age){
this.name = name;
this.age = age;
}
*/
2、让原型对象重新指向原来的构造函数
//以对象形式进行赋值,修改原型对象方法,手动指会原来构造函数
Person.prototype = {
//新添加的对象,把原来的对象覆盖掉了
constructor:Person,
sayhello:function(){
console.log("大家好,我是"+this.name)
},
kongfu:function(){
console.log("我会功夫");
}
}
//实例化对象
var p1 = new Person('张无忌',22);
var p2 = new Person('赵敏',20);
var p3 = new Person('周芷若',21);
console.log(p1.__proto__.constructor);
console.log(Person.prototype.constructor);
//指向object ----> 指向Person
四、原型链
1、原型链是什么
实际上是指隐式原型链,和显示原型关系不大,只和显示原型产生实例一瞬间起作用。
从对象的__proto__开始,连接所有的对象,就是对象查找属性或方法的过程。
2、查找对象属性基本流程
(1)当访问一个对象属性时,先往实例化对象在自身中寻找,找到则是使用。
(2)找不到(通过_proto_属性)去它的原型对象中找,找到则是使用。
(3)没有找到再去原型对象的原型(Object原型对象)中寻找,
直到找到Object为止,如果依然没有找到,则返回undefined。
五、终极原型链
(1)大写Function是生成构造函数的工具,Function创建了所有构造函数。大写Function自己生成了自己,隐式原型指向自己的显示原型。
(2)所有的实例都是Object创建的。