1.new关键字
- 首先创建一个空对象,这个对象将会作为执行构造函数之后返回的对象实例。
- 使创建的空对象的原型(
__
proto__
)指向构造函数的prototype属性。 - 将这个空对象赋值给构造函数内部的this,并执行构造函数逻辑。
- 根据构造函数执行逻辑,返回创建的对象或构造函数的显式返回值。
function Person(name) => {
this.name = name
}
const person = new newFunc(Person, 'jack')
function newFunc(...args) {
const constructor = args.shift()
const obj = Object.create(constructor.prototype)
const result = constructor.apply(obj, args)
return (typeof result === 'object' && result != null) ? result : obj
}
console.log(person)
// {name: 'jack'}
2.继承
ES5中,通过原型链实现继承:
Child.prototype = new Parent()
不同的Child实例的__proto__会引用同一Parent的实例。
通过构造函数实现继承:
function Child(args) {
Parent.call(this, args)
}
只实现了实例属性继承,Parent原型方法在Child中不可用。
ES6中,class extends实现(ES5中的语法糖):
class DateConstructor extends Date {
constructor() {
super()
this.foo = 'bar'
}
getMyTime() {
return this.getTime()
}
}
3.jQuery中的对象思想
$('p').addClass('className')
$.ajax = function () {}
$
像是一个函数,又像是一个对象;实际上,当调用$
(‘p’)时,最终返回的是dom,而dom.__proto__指向了$
.fn,fn是包含了多种方法对象集合,因此返回的结果可以在其原型链上找到addClass。同时,ajax方法是直接挂载在构造函数$
上的,是一个静态属性方法。
相当于:
class $ {
static ajax() {}
constructor(selector, context) {
this.selector = selector
this.context = context
}
addClass() {}
}
4.类继承和原型继承的区别
传统面向对象语言的类继承会引发一些问题:紧耦合、脆弱基类、层级僵化、必然重复性、大猩猩-香蕉(得到了不需要的属性)。
原型继承的本质是使用对象组合,这样可以避免复杂纵深的层级关系,不会影响到其他实例。