文章主要有两个目的:
- 理解javascript的prototype 与 proto
- 理解javascript的继承
proto 与 prototype
proto
- 除了null/null之外的变量都有__proto__属性;
- proto 能够直接访问;
var p = { sayGoodBuy: function(){ console.log('buybuy'); },
}
undefined
var s = {
}
undefined
s.__proto__
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
Object.setPrototypeOf(s,p)
{}__proto__: sayGoodBuy: ƒ ()__proto__: Object
s.__proto__
//{sayGoodBuy: ƒ}
prototype:
- Funcion中定义;
- 在new 实例化后的对象的__proto__;
var Person = function(name,age){
this.name = name;
this.age = age;
}
Person.prototype = {
constructor : Person.prototype.constructor,
sayHi: function(){
console.log(`hi, i am ${this.name}`);
}
}
{constructor: ƒ, sayHi: ƒ}
var p = new Person('sfg',32);
p.__proto__ === Person.prototype
//true
p.sayHi()
//VM5858:4 hi, i am sfg
我们的new 其实是做了什么事情的?抄别人的面向对象和原型——永不过时的话题
- 首先创建一个空对象,这个对象将会作为执行 new 构造函数() 之后,返回的对象实例
- 将上面创建的空对象的原型(proto),指向构造函数的 prototype 属性
- 将这个空对象赋值给构造函数内部的 this,并执行构造函数逻辑
- 根据构造函数执行逻辑,返回第一步创建的对象或者构造函数的显式返回值;
var newFunction = function(){
const target = Array.prototype.slice.call(arguments,0,1)[0],
args = Array.prototype.slice.call(arguments,1);
let obj = Object.setPrototypeOf({},Object.create(target.prototype));
let result = target.apply(obj,args);
if(result && typeof(result) === 'object'){
return result;
}
return obj;
}
实现继承,抄别人的面向对象和原型——永不过时的话题
- 原型链继承
Child.prototype = new Parent()
- 构造方法继承
function Child (args) {
// ...
Parent.call(this, args)
}
- 组合继承
function Child (args1, args2) {
// ...
this.args2 = args2
Parent.call(this, args1)
}
Child.prototype = new Parent()
Child.prototype.constrcutor = Child
- 一个比较完整的继承
完整的继承所需要的步骤:
- 修复prototype
- 修复constructor
- 修复超类
- 继承静态参数
var inh = function(s,p){
s.prototype = Object.create(p.prototype);
s.prototype.constructor = s;
s.super = s;
if(Object.setPrototypeOf){
Object.setPrototypeOf(s,p);
}else if(s.__proto__){
s.__proto__ = p;
}
}