constructor对于引用类型来说是可以修改的,但是对于基本类型是只读的。
typeof 用于判断一个变量的类型,但是在判断object类型时,不能说明该object属于哪一种object
instanceof 用于监测constructor.prototype是否存在于参数object的原型连上
关于new的模拟,首先需要知道会发生哪些事:
我们了解过一些关于原型、原型链知识点后知道一个实例可以:
function my_new() {
var obj = new Object() // 创建一个新对象
Con = [].shift.call(arguments) // 取出需要(外部传入的)的构造函数
obj.__proto__ = Con.prototype // 将obj的原型指向构造函数,这样obj就可以访问到构造函数的属性
var result = Con.apply(obj, arguments) // 使用apply,改变构造函数的this到新建的对象,这样obj就可以访问到构造函数的属性
return typeof result === 'object' ? result : obj // 确保返回的是个对象
}
原理:将父级的构造函数this指向了子级构造函数的实例上
局限: 父级的原型链并没有被子级改变
function Mydad() {
this.fatherName = 'hi dad'
console.log('dad的this' , this)
}
function Mychild() {
Mydad.call(this)
console.log('child的this' , this)
}
Mydad.prototype.sayHi = function(){
console.log('hi you~~~')
};
var child1 = new Mychild()
console.log(child1)
Mydad.prototype.sayHi = function(){
console.log('hi you~~~')
};
这种方式,子级就没有办法继承
原理:通过prototype的让实例对象的原型指向父级
局限:
原型链继承和构造函数继承一起使用
缺陷:在实例子类的时候,父类构造函数执行了两次
原理:如果想要继承父类的原型对象,就直接给他父类的原型对象
缺陷:会造成子类实例对象直接指向父级原型
Mychild.prototype = Object.create(Mydad.prototype) // 增加了一级__proto__相当于隔离了Mychild,Mydad
// 使用下面这种方式也可以
Child.prototype = new Parent(); // 但是如上说了,会执行两次
原理: ES5 Object.create 的模拟实现,将传入的对象作为创建对象的原型
缺陷: 包含引用类型的属性值会始终共享,跟原型链继承一样
function mychild(obj) {
function Mydad(obj) {
this.fatherName = 'hi dad'
}
Mydad.prototype = obj
return new Mydad()
}
var person = {
name: 'hahaha',
type: [999]
}
var child1 = mychild(person)
var child2 = mychild(person)
child1.type.push(333)
console.log(child1)
console.log(child2)
原理:创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。类似于借用构造函数一样,每次创建对象都会创建一遍方法
function mychild(obj) {
var clone = Object.create(obj); // 创建一个新对象
clone.sayName = function () {
console.log('hi'); // 以某种方式来增强这个对象
}
return clone; // 返回这个对象
}
var person = {
name: 'hahaha',
type: [999]
}
var child1 = mychild(person)
var child2 = mychild(person)
child1.type.push(333)
console.log(child1)
console.log(child2)