一、构造函数(用ES6之前的方法)
function Star(uname, age) { // 构造函数
this.uname = uname;
this.age = age;
this.sing = function () {
console.log('123');
}
}
var ldh = new Star('Ldh', 18); // 使用构造函数创建对象
ldh.sing();
1.实例成员
(1)实例成员是构造函数内部通过this添加的成员,如uname, age, sing都是实例成员。
console.log(ldh.uname); // 访问实例成员
(2)实例成员只能通过实例化的对象来访问。
2.静态成员
(1)静态成员是在构造函数本身上添加的成员。
Star.gender='男'; // 创建静态成员
(2)静态成员只能通过构造函数来访问
console.log(Star.gender); // 访问静态成员
3.构造函数的缺点
浪费内存空间。
在创建对象时,简单数据类型如属性可以存放在一起,但是复杂数据类型如函数却新开辟了一个空间,每一个对象的复杂数据类型都新开辟了一个属于自己的新空间,但是很多对象的函数功能都是一样的,这样就造成了内存空间浪费的问题。
4.解决方法:构造函数原型:prototype
原型就是为了共享函数,简化内存。
每个构造函数都有一个prototype,把不变的方法都定义在phrototype对象上,可以让所有的对象实例共享这些方法。
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
Star.prototype.sing = function () {
console.log('123');
}
var ldh = new Star('Ldh', 18); // 使用构造函数创建对象
ldh.sing(); // 使用原型
5.__proto__
在刚刚新建对象之后,我们可以输出ldh查看是否存在ptototype,
Star {uname: 'Ldh', age: 18}
age: 18
uname: "Ldh"
[[Prototype]]: Object
此时,输出的结果时这样的,可以看到里面也有prototype的相关内容。
我们如果想要访问这个原型对象
console.log(ldh.__proto__); //访问实例对象的原型对象
// 结果:{sing: ƒ, constructor: ƒ}
相当于Star.prototype
console.log(ldh.__proto__ === Star.prototype);//结果:true
6.函数的查找顺序:
在执行ldh.sing(); 时,先查找ldh实例对象本身是否有sing的方法,如果有的话就执行这个对象上的sing函数,如果没有的话就去查找__proto__,去构造函数原型对象上去找sing()函数。如果原型上面也没有就报错。ldh.sing is not a function。
7.称呼
prototype:原型对象
__proto__:对象的原型
8.构造函数 constructor
prototype和__proto__中都有一个constructor函数,用来指向构造函数,是谁创建的原型就指向谁。
console.log(ldh.__proto__.constructor); // 访问构造原型的构造函数
//返回的结果就是构造函数本身
ƒ Star(uname, age) {
this.uname = uname;
this.age = age;
}
9.constructor被覆盖的原因
我们在实际工程中,原型对象包含的函数不止一个,会出现以下情况
Star.prototype = {
sing: function () {
console.log(123);
},
dance: function () {
console.log(456);
}
}
用这种方法用更加条理清晰,但是这种方法是利用对象把原来的prototype给覆盖掉,constructor也被覆盖掉
Star.prototype = {
constructor: Star; // 用constructor指回原来的构造函数
sing: function () {
console.log(123);
},
dance: function () {
console.log(456);
}
}
10.原型链
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
Star.prototype = {
constuctor: Star,
sing: function() {
console.log(123);
},
dance: function() {
console.log(456);
}
}
var ldh = new Star('ldh', '234'); // 新建实例对象
Object.prototype.sex = 'nan'; // 按照原型链的查找机制,则先找实例对象本身的成员,再按照原型链往上找,都没有就返回空
Star.prototype.sex = 'nv';
console.log(ldh.sex); // 结果:nv
11.this指向问题
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
var that;
Star.prototype.sing = function() {
console.log(123);
that = this;
}
var ldh = new Star('ldh', '234'); // 新建实例对象
ldh.sing();
console.log(that == ldh); // 结果:true
原型对象函数里的this指向的是实例对象。
12.扩展内置对象方法
给数组原型对象添加一个求和的方法。
Array.prototype.sum = function() {
var sum = 0;
for (var i = 0; i < this.length; i++) {
sum += this[i];
}
return sum;
}
var arr = [12, 4, 6, 7, 4, 3];
console.log(arr.sum());