一、由来
- 当初在设计javascript时不想引入类的概念,但要实现类的功能。借鉴了高级面向对象语言中,创建一个实例时,其实就是执行了该类的构造函数,因此,作者用 new + 构造函数 的形式来表示生成的实例。这里提到的构造函数其实就是我们平时常见到的普通函数,只是为了区分,首字母大写。
- 还有一个问题:这样创建出来的实例,来自同一个“类”,但却不知道,这时提出了prototype的概念,用来存放该实例的构造函数。
- 除了通过bind绑定的没有,每个函数都有prototype属性,prototype属性包含了contructor和在构造函数中定义的所有属性和方法。其中,contructor是真正存放该实例的构造函数的地方。
二、与constructor的关系
其实真正存放实例的构造函数是在constructor,constructor指向构造函数,constructor又是prototype的属性,prototype还是构造函数的属性。是不是乱了,反正我是傻了~~
三、prototype 和 __proto__ 区别:
构造函数对应的是prototype,实例对象对应的是_proto_,两者都是相同的,都指向构造函数的原型。
例子:
function Demo(){ this.name = "demo"; } const demo = new Demo(); console.dir(Demo.prototype); console.dir(demo.__proto__); console.log(Demo.prototype == demo.__proto__);
四、相关的方法
1.判断实例的构造函数:Object instanceof Function 和 Function.prototype.isPrototypeOf(Object)
例如:
function Demo(){ this.name = "demo"; } const demo = new Demo(); console.log(demo instanceof Demo); console.log(Demo.prototype.isPrototypeOf(demo));
2.检测属性来着与实例还是原型:hasOwnProperty()
例如:
function Demo(){ this.name = "demo"; } Demo.prototype.age = 11; const demo = new Demo(); console.dir(demo.name+'.....'+demo.hasOwnProperty('name')); //demo.....true console.dir(demo.age+'.....'+demo.hasOwnProperty('age')); //11.....false
五、易混的概念
难点:
(1)函数即对象
在JS里,函数就是Function函数的实例对象,函数即是对象。
function Fun(){
console.log('fun');
}
const fun1 = new Fun(); //对象由函数创建
console.log(Fun.constructor); //Function 结论:Fun 的构造函数是 Function
console.log(Function.constructor); //Function 结论:Function 的构造函数还是是 Function
console.log(Object.constructor); //Function 结论:Object 的构造函数还是是 Function
//结论:对象由函数创建,函数都是Function函数的实例对象,也就是函数即对象
(2)constructor 的理解
一个拿来保存自己构造函数引用的属性。由于同一个构造函数生成的实例的constructor 值的一样,为了节省内存空间,constructor被当成共享属性,存放在prototype(下文会介绍到)中。
(3)prototype 的理解
目的:为了内存着想,专门存放共享属性和方法的地方。 在自身存放在这些实例的构造函数上。又称为原型对象。
function Foo(){
console.log('Foo');
}
const foo1 = new Foo(); //Foo
const foo2 = new Foo(); //Foo
//两个实例添加相同作用的方法
foo1.say = function(){
console.log('hello!!!');
}
foo2.say = function(){
console.log('hello!!!');
}
console.log(foo1.say === foo2.say); //false //尽管二者的代码相同,但在我们的内存里,却存放了两份一模一样的东西,造成内存的浪费
//prototype的好处:
Foo.prototype.show = function(){
console.log("This is a show function");
}
foo1.show(); // This is a show function
foo2.show(); // This is a show function
console.log(foo1.show === foo2.show); //true //这时,内存的存储空间也是相同的,没有造成浪费
(4)__proto__属性
目的:让实例能找到自己的原型对象
特点:只要是对象就会有__proto__属性
(5)原型链
__proto__ 把原型对象和实例串起来的的形式,就是原型链