构造函数的创建
构造函数是用来生成对象的,可以重复使用
使用this来定义对象中的键值对,this可以代表生成的对象
构造函数的首字母通常大写
function Person(){
this.name = '张三'
}
使用new来实例化一个构造函数,也就是生成一个对象
const obj = new Person();
console.log(obj); // 打印 {name:'张三'}
如果new时没有参数,可以省略小括号
const obj = new Person;
实例成员和静态成员
实例成员:通过在构造函数中this.属性 = 值创建的成员
静态成员:通过构造函数.属性 = 值创建的成员
静态成员不需要实例化构造函数就可以使用,因为他是在构造函数上创建的
function Person(age){
// age 就是实例成员
this.age = age
}
// say 就是静态成员
Person.say = 'haha';
const obj = new Student(20);
console.log(obj.age); // 20
console.log(Person.say); // haha
原型对象(prototype)
使用构造函数生成多个对象时,对象中可能会有相同的属性或方法
为了避免每次实例化对象时,都重复生成相同的属性或方法
可以将相同的属性或方法拿出构造函数,存储在公共区域
这个公共区域就是原型对象
js为每个构造函数都提供一个内置属性prototype,他的值是一个对象
function Person(name){
this.name = name
}
// 向原型对象内添加read方法
Person.prototype.read = function(){
console.log('看书')
}
// new出来的对象都会有read方法,并且是同一个
const obj1 = new Person('张三');
const obj2 = new Person('李四');
obj1.read(); // 打印'看书'
obj2.read(); // 打印'看书'
consoel.log(obj1.read === obj2.read); // 打印true
可以直接向prototype赋值,但是需要补充constructor属性
Person.prototype = {
constructor:Person,
read:function(){
console.log('看书')
}
}
构造函数(constructor)
constructor是原型对象上的一个内置属性,他指向该原型对象所属的构造函数
console.log(Person.prototype.constructor);
// 打印构造函数Person:
// ƒ Person(){
// this.name = '张三'
// }
console.log(Person.prototype.constructor === Person); // 打印true
new出来的实例化对象没有constructor属性,但是他会去原型对象上找(原型链)
console.log(obj1.constructor === Person); // 打印true
js中有许多内置的构造函数,比如Array、Function等等
我们创建出的数组函数等等都是有constructor属性的
const arr = [1,2,3];
console.log(arr.constructor); // 打印 ƒ Array() { [native code] }
const fun = function(){}
console.log(fun.constructor); // 打印 ƒ Function() { [native code] }
同样的,这些构造函数也可以new,new Array也可以得到一个数组
// new Array的参数只有一个时,则表示数组的长度
const arr = new Array(1,2,3);
console.log(arr); // 打印 [1,2,3]
// new Function的最后一个参数表示函数体,前面的参数表示形参
// 所有参数都以字符串的形式传递
const fun = new Function('a','b','console.log(a+b)');
fun(1,2); // 打印3
console.log(fun); // 打印fun函数
// ƒ anonymous(a,b) {
// console.log(a+b)
// }
原型(__proto__)
每个实例化对象都有一个__proto__属性,指向原型对象
console.log(obj1.__proto__);
// 打印原型对象:
// {read:ƒ, constructor:ƒ}
console.log(obj1.__proto__ === Person.prototype); // 打印true
原型链
查找属性或方法按照原型链的顺序,遵循就近原则。
当使用一个实例化对象的属性或方法时,他会首先找自身,有就使用
自身没有,就在原型对象中找,有就使用
原型对象没有,再找原型对象的原型对象,有就使用
直到找到最顶层的原型对象(Object.prototype)
这种根据原型对象的链式结构,进行的链式查找方式,通常也叫做原型链
(从查找对象成员方式的角度)
原型链继承
继承就是在原型链上增加一个构造函数和一个原型对象
将一个构造函数的的实例化对象赋值给另一个构造函数的原型对象即可
function Person(){
this.age = 20;
this.sex = '男'
}
function Student(){
this.age = 10
}
// 通过将实例化对象赋值给原型对象,实现继承
Student.prototype = new Person()
// 别忘记将constructor重新指向原来的构造函数
Student.prototype.constructor = Student
const obj = new Student();
console.log(obj.age); // 打印10
console.log(obj.sex); // 打印'男'
此时Student的实例化对象,可以使用Person的实例成员以及原型对象上的公共成员。
由于原型链的就近原则,打印的age为Student中定义的10,而不是Person中的20