new 一个对象的步骤
1.创建一个空对象instance
2.设置空对象的原型链继承自创建这个空对象的构造函数的原型 instance.proto=F.prototype;
3.构造函数执行 this 指向新事例
4.判断构造函数的返回结果是对象类型就返回这个对象,前边就废了,如果不是就返回原来的instance
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| { function M() { this.a = 1; } let o = new M() //函数的prototype有个constructor属性 指向本身的构造函数 如果重新定义了prototype则为false; M.prototype.constructor === M //true // js里所有的对象都有proto属性,指向构造该对象的构造函数的原型(用于继承) //原型prototype是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法 o.__proto__ === M.prototype //true M.__proto__ === Function.prototype //true 一层一层向上找 //instanceof 的原理就是判断实例对象的__proto__和 构造函数的原型是不是引用同一个地址 M.prototype.__proto__ === Object.prototype //true console.log(o instanceof M) //true console.log(o instanceof Object) //true
// 那么如何判断 o 到底是谁创建的呢 console.log(o.__proto__.constructor === M) //true
}
|
继承方式
1.借助构造函数 实现继承(call),但是父类的原型链的方法 子类无法继承,只能继承父类构造函数里边的属性和方法。
1 2 3 4 5 6 7 8 9 10 11
| function Parent(){ this.name = 'parent' } Parent.prototype.say = function () {...}
function Child(){ Parent.call(this) this.type = 'child' }
console.log(new Child()) //{name:parent,type:child} 注意,没有父类原型的方法
|
2.原型链实现继承 由于子类的的对象原型链都是父类是一样的,所以改变一个子类的继承父类的属性,另一个子类也变了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function Parent(){ this.name = 'parent'; this.arr = [1,2,3] }
Parent.prototype.say = function () {console.log("say parent")}
function Child(){ this.type = 'child' }
Child.prototype = new Parent()
console.log(new Child().name ) //parent console.log(new Child().say() ) //say parent
var c1 = new Child() var c2 = new Child() c1.arr.push(4) console.log(c1.arr ,c2.arr) //[1,2,3,4] [1,2,3,4]
|
3.组合继承方式 防止上边两种的缺点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function Parent() { this.name = 'Parent' this.arr = [1,2,3] }
function Child(){ Parent.call(this) this.type = 'child' } Child.prototype = new Parent()
var c1 = new Child() var c2 = new Child()
c1.arr.push(4)
console.log(c1.arr,c2.arr)
|