构造函数和原型系列学习扩展

1、构造函数

构造函数也是一个普通函数,唯一的区别是调用方式不一样(构造函数习惯上首字母大写)
构造函数主要用来初始化对象,可以把对象中一些公共的属性和方法抽取处理,然后封装到函数里面
在全局上下文中,函数调用中直接使用this,this指向window
构造函数——this指向构造出的对象

// 构造函数
function Star(uname,age) { 
	this.uname = uname
	this.age = age
	this.sing = function() {
		console.log("唱歌")
	}
} 
// foo为当前实例的对象(构造函数绑定的对象为当前实例的对象,this指向构造出的对象)
var foo = new Star('zyzhang',18)
console.log(foo)

// 补充:除了使用构造函数创建对象,常见的还要利用new Object()创建对象 和 利用对象字面量创建对象

1.1、静态成员和实例成员

实例成员就是构造函数内部通过this添加的成员(如:uname、age、sing就是实例成员)
实例成员只能通过实例化对象来访问(如foo.name 而Star.name 是不允许的)

静态成员在构造函数本身上添加的成员
静态成员只能通过构造函数来访问(如:Star.age 而foo.age是不允许的)

构造函数存在的问题:

构造函数方法很好用,但是存在浪费内存的问题
如:我们实例化多个对象,上面的构造函数中的sing函数会开辟多个内存空间
如果我们希望所有对象使用同一个函数,该怎样做呢??? =====》 原型对象

1.2、构造函数原型 prototype

prototype属性是函数独有的,从一个函数指向一个对象,它的含义是函数的原型对象,也就是这个函数所创建的实例的原型对象。
我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。

于是我们的代码就可以这样写了:

function Star(uname,age) { 
	this.uname = uname
	this.age = age
} 
Star.prototype.sing = function() {
	console.log("唱歌")
}
var foo = new Star('zyzhang',18)
var foo2 = new Star('zyzhang2',19)
foo.sing()  foo2.sing()

1.3、总结

原型是什么? 一个对象,也称为prototype为原型对象
原型对象的作用是什么? 共享方法

疑问??? 上面的sing函数是定义在Star这个构造函数的原型对象(prototype)身上,为什么上面的foo这个实例对象可以使用这个方法呢?
这是因为foo这个实例对象身上也有一个对象叫__proto__

2、对象原型__proto__

__proto__属性是对象所独有的;
__proto__属性都是由一个对象指向一个对象(指向它们的原型对象,也可以理解为父对象)
每一个对象(除null)都会有的属性__proto,这个属性指向该对象的原型。
foo. proto === Star.prototype
方法查找规则:首先看foo对象身上是否有sing方法,有就执行这个对象上的sing,如果没有,因为 __proto__的存在,就去构造函数原型对象prototype身上去找sing这个方法。

3、constructor 构造函数

对象原型( proto)和构造函数原型对象(prototype)里面都有一个属性constructor属性,constructor也称之为构造函数,因为它指向构造函数本身

constructor属性也是对象所独有的;
constructor主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数

很多情况下,我们需要手动的利用constructor这个属性指回原来的构造函数,如下实例:

function Star(uname,age) { 
	this.uname = uname
	this.age = age
} 
Star.prototype = {
	// 如果修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor这个属性指回原来的构造函数
	constructor: Star, 
	sing: function() {
	},
	movie: function() {
	}
}

var foo = new Star('zyzhang',18)
var foo2 = new Star('zyzhang2',19)
foo.sing()  foo2.sing()

4、三者之间的关系

在这里插入图片描述

5、原型链

我们关注一下上面的Star原型对象,也是一个对象,那么Star.prototype__proto__指向的是什么呢?
通过打印我们发现 我们的Star原型对象里面的__proto__原型指向的是Object.prototype
具体通过如下图了解具体内容(图片来源于网络)
在这里插入图片描述

6、JavaScript的成员查找机制(规则)

1)当访问一个对象属性(包括方法)时,首先查找这个对象自身有没有该属性
2)如果没有就查找它的原型(也就是__proto__指向的prototype原型对象
3)如果还没有就查找原型对象的原型(Object的原型对象)
4依次类推一直找到Object为止(null)

7、原型对象this指向

1、构造函数中里面this指向的是实例对象(foo)
2、原型对象函数里面的this指向的是实例对象(foo)

8、拓展内置对象

我们知道Array.prototype里面有很多方法(如:pop,push,sort等等)但是没有求和 的方法,这时我们就可以通过数组的原型对象自定义一个方法(如sum)

Array.prototype.sum = function() {
	var sum = 0;
	for(var i = 0; i< this.length;i++) {
		sum += this[i]
	}
	return sum;
}

9、继承

ES6之前并没有提供extends继承。可以通过构造函数+原型对象模拟实现继承,被称为组合继承

9.1 call()

调用这个函数,并且修改函数运行时的this指向

fun.call(thisArg, arg1, arg2, ...)
// thisArg:当前调用函数this的指向对象
// arg1,agr2:传递的其他参数

先看如下代码

<script>
    function fn() {
      console.log(this)
    }
    var o = {name: "zyzhang"}
    // fn()
    fn.call()
    // 此时这个普通函数中的this指向的时Window这个对象
</script>

此时如果我们需要改变这个函数的this指向就可以这个做:

fn.call(o) // 此时函数中的this指向o这个对象

9.2 借用构造函数继承父类属性

如下代码子类就继承了父类的属性:

// 借用父构造函数继承属性
// 1 父构造函数
function Father(uname,age) {
	// this指向父构造函数的对象实例
	this.uname = uname;
	this.age = age;
}

// 2 子构造函数
function Son(uname,age, score) {
	// this 指向子构造函数的对象实例
	Father.call(this,uname,age)
	this.score = score
}
var son = new Son("zyzang",18,100)
console.log(son)

9.3 借用构造函数继承父类的方法

// 1 父构造函数
function Father(uname,age) {
	this.uname = uname;
	this.age = age;
}

// 2 子构造函数
function Son(uname,age, score) {
	Father.call(this,uname,age)
	this.score = score
}

// Son.prototype = Father.prototype 这样赋值会有问题,如果修改子原型对象,父原型对象也会跟着一起变化

Son.prototype = new Father()
// 如果利用对象形式修改了原型对象,别忘了利用constructor指回原来的构造函数
Son.prototype.constructor = Son;
// 子构造函数专门的方法
Son.prototype.exam = function() {
	console.log("考试")
}
var son = new Son("zyzang",18,100)
console.log(son)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值