创建对象的方式
- new Object()
- 对象字面量
- 工厂函数
- 自定义构造函数
构造函数和实例对象的关系
- 构造函数是实例对象抽象出来的模版
- 实例对象是构造函数模版得到的具体实例对象
- 每一个实例对象都通过一个constructor属性,指向创建改实例的构造函数(⚠️:constructor是原型对象的属性,但是属性查找是在原型链上进行查找的,所以可以通过实例对象访问到constructor属性)
- 可以通过constructor属性判断实例和构造函数之间的关系(⚠️:推荐使用instanceof操作符)
静态成员和实例成员
- 实例成员:构造函数中this上的成员
- 静态成员:构造函数上添加的成员
- 实例成员只能由实例对象调用
- 静态成员只能有构造函数打点调用
- 实例对象也可以访问到原型对象上的成员
function Person(name, age) {
this.name = name;
this.age = age;
this.sayHi = function () {
console.log('Hello...')
}
//上述的name\age\sayHi就是实例成员
}
Person.hobby = 'running'
Person.climb = function () {
console.log('Climbing...')
}
//上述的hobby和climb就是静态成员
Person.prototype.jump = function () {
console.log('Jumping...')
}
//jump为p1的__proto__属性指向的它的原型对象上的成员
//===============那么,
var p1 = new Person('Lucy', 29)
console.log('实例成员')
console.log(p1.name ) //'Lucy'
console.log(p1.age) //29
p1.sayHi() //Hello...
console.log('原型对象的成员')
p1.jump() // Jumping...
console.log('静态成员')
Person.climb() //Climbing...
console.log(Person.hobby) //running...!
运行结果:
构造函数的问题
- 浪费内存
function Student(name, id) {
this.name = name;
this.id = id;
this.type = "student";//this内部的type属性值是不变的
//每个对象的 message方法都是一样的
this.message = functon(){
console.log(this.name + "," + this.id);
}
}
- 每个构造函数都有一个prototype属性,指向构造函数的原型对象,这个原型对象的属性和方法,都可以被构造函数的实例对象所访问。因此,我们可以将实例对象的共有属性和方法添加给原型对象,解决构造函数的内存浪费问题
构造函数、实例、原型对象之间的关系
原型链![请添加图片描述](https://i-blog.csdnimg.cn/blog_migrate/ad985556f0603bb6df1e17301ce62214.png)
原型链查找机制
- 搜索某个对象的属性或方法时,都会先从实例中查找,如果找到则返回
- 如果没找到,则会在该对象的构造函数的原型对象上查找,找到则返回
- 如果没找到,继续在该原型对象的构造函数的原型对象上查找
- 如果一直到原型链的末端都没找到,则返回undefined
实例对象读写原型对象成功
1、值类型成员写入
- 该行为会屏蔽掉原型对象成员的访问,会将该成员添加到自己身上
2、引用类型成员写入同理
3、复杂类型成员修改
- 同样会先在自己身上查找,找到则修改
- 如果自己身上没有,则沿着原型链继续查找,找到则修改
- 如果在原型链的末端还没有找到该成员,则报错
更简单的原型语法
// 自定义构造函数
function Person(name,age) {
this.name = name;
this.age = age;
}
// 将所有实例共享的属性和方法,都添加给原型对象
// Person.prototype.type = "human";
// Person.prototype.sayName = function () {
// console.log(this.name);
// };
// 直接使用一个对象字面量对 原型对象进行赋值
Person.prototype = {
constructor : Person, // 需要手动 将 constructor 属性指向正确的构造函数
type : "human",
sayName : function () {
console.log(this.name);
}
};
// 生成对象实例
var person1 = new Person("Bob",18);
var person2 = new Person("Mike",20);
person1.sayName();
console.log(person2.constructor);
执行结果:
原生对象的原型对象
扩展js中内置的构造函数的实例的方法
Array.prototype.getEvenSum = function () {
// 获取数组中每一项的方式
// this[i]
var sum = 0;
for (var i = 0; i < this.length; i++) {
if (i % 2 === 0) {
sum += this[i];
}
}
return sum;
};