原型,继承
声明对象的三种方法:
1,var obj={}
2,var obj = new Object()
3,构造函数
这里我们着重讲解构造函数的方法
function Person(name, age) {
this.name = name
this.age = age
}
var zs = new Person('ZS', 12)
在基础的js给对象添加方法
zs.say = function(){}
这种方法当需要添加的方法很多时代码冗余 因此引出了可以在构造函数中添加
function Person(name, age) {
this.name = name
this.age = age
this.say = function(){}
}
var zs = new Person('ZS', 12)
但是这种方法 仍有缺陷 每创建一个实例对像 都会在内存中开一片空间用来存放say方法 会造成内存的浪费
所以就有了 通过原型添加的方法
1, 每个函数在生成时都会自带一个原型对象,不只是只有构造函数才有的
- 原型对象中放着所有实例对象公用的属性和方法
3, 每个实例对象自带一个constructor 指向创造自己的构造函数
所以,在更改原型对象时一定要设置constructor 指向
不然实例对象找不到自己的构造函数
4, 同时 函数也是对象,所以函数有prototype和__proto__属性
而,对象只有__proto__属性,这个属性是用来访问构造函数的原型对象
Person.prototype.say = function() {}
不过还是那个问题,添加的方法多了就会有代码冗余
所以 最终好最好的方法就是直接创建一个prototype对象
Person.prototype = {
constructor: Person,
say: function() {}
}
注意:在操作原型对象时必须让对像的constructor指向Person构造函数 不然通过构造函数实例化出来的对象找不到prototype
继承
1,原型链继承:子类通过prototype的方式将所有父类通过prototype方式添加的属性和方法继承过来
function Person() {}
Person.prototype.fa='zs'
function Son() {}
Son.prototype = new Person()//原型继承必须在给Person.prototype添加方法和属性后边
var s = new Son()
//注意实例化必须在原型继承后边
//只能继承父类通过prototype添加的属性和方法
2,对象冒充:在子类中创建一个临时属性,让这个临时属性指向父类构造函数,然后执行这个临时属性指向的函数,最后在销毁临时属性
function Preson(name, age) {
this.name = name
this.age = age
this.say = function() {
console.log(this.name, this.age);
}
}
function Son(name, pwd, age) {
this.name = name
this.pwd = pwd
this.method = Preson //让临时属性指向Person函数
this.method(name, age) //执行这个函数 函数的参数是Person中的参数
delete this.method //销毁临时属性
}
var p = new Preson('zs', 13)
var son = new Son('lis', '123', 12)
p.say() //zs 13
son.say() //lis 12
3,call方法继承:call是函数对象特有的方法 有两个个参数 第一个赋值给调用者的this ,第二个赋值给调用者的参数
function Preson(name) {
this.name = name
this.say = function() {
console.log(this.name);
}
}
function Son(pwd) {
this.pwd = pwd
}
var s = new Son('123')
Preson.call(s, 'zs') //第一个参数赋值给Person中的this,第二个参数赋值个Person中的参数
s.say() //zs
4,apply方法继承:apply和call类似 有两个参数 不过第二个参数是数组 第一个赋值给调用者的this ,第二个依次赋值给调用者的参数
function Preson(name, age) {
this.name = name
this.age = age
this.say = function() {
console.log(this.name, this.age);
}
}
function Son(pwd, name, age) {
this.pwd = pwd
Preson.apply(this, new Array(name, age)) //第一个参数赋值给Person中的this,第二个参数赋值个Person中的参数
}
var s = new Son('123', 'lis', 23)
s.say() //lis 23
5,混合继承:通过call和apply方法继承有不足,他们无法继承通过prototype添加的方法和属性 可以通过call+原型链混合继承
function Preson(name) {
this.name = name
this.say = function() {
console.log(this.name);
}
}
Preson.prototype.eat = function() {
console.log(9999);
}
function Son(pwd, name) {
this.pwd = pwd
// call继承
Preson.call(this, name) //第一个参数赋值给Person中的this,第二个参数赋值个Person中的参数
}
// 原型链继承
Son.prototype = new Preson()
var s = new Son('123', 'zs') //注意:实例化必须在原型链继承后
s.say() //zs
s.eat() //9999