我们解说一下这个图:
// 这个是一个构造函数
function Foo(name){
this.name = name;
}
// 这个是两个构造函数实例。f1, f2 。
var f1 = new Foo('F1'); // 对象的由来在本文章下面有
var f2 = new Foo('F2');
函数都有一个prototype属性,这个属性是一个对象。叫做原型对象。可以理解为是new出来实例的公共属性和方法。
Foo.prototype -> {}
每一个对象包括函数(函数也是对象),都有一个私有属性 __proto__(两个下划线), 不光普通对象有,原型对象也有__proto__,函数也有。
首先说:
__proto__
f1 和 f2 的__proto__ 都指向的是Foo.prototype 。
Foo.prototype的__proto__指向了Object.prototype 。
Foo 的__proto__指向了Function.prototype。
Function.prototype的__proto__指向了Object.prototype。
Object.prototype 的__proto__指向了null,为什么是null(应该是规定吧)。
contructor
对象和函数都有一个contructor指向的是它的构造函数。
f1 和 f2 的contructor 指向的是 function Foo() {} 这个构造函数。
Foo.prototype.contructor 也指向的是 function Foo() {} 这个构造函数。
Foo 是函数也是对象,Foo.contructor 指向的是function Function() { }这个构造函数。因为函数都是Function的实例。
Object.prototype.contructor 指向的是 function Object();
Function.prototype.contructor 指向的是 function Function();
Object
function Object(){} 内置对象。
Object.prototype 的__proto__指向了null。
Object.prototype.contructor 指向的是 function Object() 。
Object的__proto__指向了Function.prototype。
Function
function Function{}() 内置对象。
Function.prototype的__proto__指向了Object.prototype。
Function.prototype.contructor 指向的是 function Function() 。
Function的__proto__指向了Function.prototype。
总结:
函数即是对象又可是构造函数。
对象:(包含函数也是对象), 都有__proto__ 属性,指向它的构造函数的原型。还有constructor属性指向了它的构造函数,就是谁new的它。
构造函数:都有prototype和__proto__属性,构造函数prototype属性指向的就是构造函数的原型。构造函数的实例的__proto__属性指向的就是构造函数的原型。原型就是一个对象,可以理解为各个实例的继承的公用方法和属性。
什么是原型链
每个对象都可以有一个原型proto,这个原型还可以有它自己的原型,以此类推,形成一个原型链。查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去向原型对象的原型对象里去寻找...... 这个操作被委托在整个原型链上,这个就是我们说的原型链了。
举一个例子:
// 首先给object 赋值一个自定义属性。
Object.prototype.apple = "a apple";
var a = {};
对象a首先寻找自身的apple ,发现没有再去寻找a.__proto__ 发现有,那么就返回。没有就返回undefined
例子2:
// 首先给object 赋值一个自定义属性。
Object.prototype.apple = "a apple";
function Foo(){
}
var f = new Foo();
console.llog(f.apple)
f -> {} -> Foo.prototype -> Foo.prototype.__proto__ 找到了返回。
先找自身,再找Foo的原型,再找原型的原型形成了链条。
例子3:
// 首先给object 赋值一个自定义属性。
Object.prototype.apple = "a apple";
function Foo(){
}
var f = new Foo();
//Object.create(proto, [propertiesObject])
//方法创建一个新对象,使用现有的对象来提供新创建的对象的proto。
// proto 表示新建对象的原型对象
var a = Object.create(f);
a.__proto__ .__proto__ .__proto__ .apple 这样就能找到apple属性。
对象是怎么构建的
(1) 创建一个新对象且将其隐式原型指向构造函数原型;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ;
(3) 执行构造函数中的代码(为这个新对象添加属性) ;
(4) 返回新对象。
//第一种形式:
function newObj(fun) {
return function () {
// 创建一个新对象且将其隐式原型指向构造函数原型
var obj = {};
obj.__proto__ = fun.prototype;
// 执行构造函数, 后面的apply是把arguments转成把数组
fun.apply(obj, Array.prototype.slice.apply(arguments));
// 返回该对象
return obj
}
}
// 使用方法
function Foo(name){
this.name = name;
}
// new了一个对象
var a = newObj(Foo)('apple');
//第二种形式:
let newMethod = function (Parent, ...rest) {
// 1.以构造器的prototype属性为原型,创建新对象;
let child = Object.create(Parent.prototype);
// 2.将this和调用参数传给构造器执行
Parent.apply(child, rest);
// 3.返回第一步的对象
return child;
};
// 使用方法
function Foo(name){
this.name = name;
}
// new了一个对象
var a = newMethod(Foo,'apple');
//参考:https://blog.csdn.net/qq_27674439/article/details/99095336
使用方法:
总结:
就是把函数里面的属性方法都挂到 新new的这个{}上面,原型也挂到这个{}上。然后在参数传过去。
网友评论