JS构造函数,原型链,原型对象总结
构造函数
构造函数第一个字母大写
使用this指向当前对象的 公有属性
var Car = function(wheels, seats, engines) {
this.wheels = wheels;
this.seats = seats;
this.engines = engines;
};
var myCar = new Car(6,3,1)
也可以创建私有属性和私有方法,它们两个在对象外部是不可访问的
用var 关键词去创建变量,代替this创建私有属性;比如,我们想记录我们的car行驶的 speed ,但是我们希望外面的代码对 speed 的修改只能是加速或减速(而不是变成字符串、直接赋值成某个速度等其他操作),那么如何达到这类操作的目的呢?
var Car = function() {
// this is a private variable
var speed = 10;
// these are public methods
this.accelerate = function(change){
speed =+ change
}
this.decelerate = function() {
speed -= 5;
}
this.getSpeed = function(){
return speed
}
}
instanceof
判断某个对象是否为某个构造函数的实例
console.log(myCar instanceof Car)
静态成员和实例成员
静态成员: 写成对象字面量的形式,直接使用对象来调用。
// 一般用于 工具 的写法,工具中使用静态成员,即工具中的方法如 max(),PI 只有一个
var MyMath = {
PI:3.1415,
max:function(){},
min:function(){}
}
MyMath.PI
MyMath.max()
实例成员:构造函数中的成员: p.sayHi()
function Person(name,age) {
this.name = name,
this.age = age,
this.sayHi = function(){}
}
//当有很多实例的时候,使用构造函数来创建
var p = new Person('zs',18)
构造函数原型
每一个构造函数都有一个属性 : 原型/原型对象 prototype
function Person(name,age) {
this.name = name,
this.age = age,
}
console.dir(Person.prototype)
//那么就可以为Person的原型对象增加方法,这样用Person构造函数创建出来的实例都可以访问新增加的方法
Person.prototype.sayHi = function() {
console.log("hi")
}
var p1 = new Person('ls',12)
var p2 = new Person('tom',13)
p1.sayHi()
p2.sayHi()
这样做的优点: 节省内存
p1.sayHi 和 p2.sayHi 是相等的,指向同一个内存空间
如果在Person()内部定义 sayHi 方法的话,新创建的p1,p2会各自在内存创建空间
对象本身有 __proto__ 属性,当调用对象的属性或方法时,先去找对象本身的属性/方法;找不到的话 再去调原型中的属性/方法
对象的__proto__ 属性 等于 构造函数的prototype,对象可以访问原型对象所有成员
p1.__proto__ === Person.prototype
> true
constructor 记录了创建该对象的构造函数
p1.constructor === Person
> true
注意:constructor 属性
function Person(){
}
var p1 = new Person()
console.log(p1.constructor === Person.prototype.constructor)
>true
原因:
当获取 person.constructor 时,其实 person 中并没有 constructor 属性,当不能读取到constructor 属性时,会沿着原型链从 person 的原型也就是 Person.prototype 中读取,正好原型中有该属性,所以:
person.constructor === Person.prototype.constructor
原型链
同理如图:
查找对象是否具有某个方法或属性时,会由底向上查找:当底层对象没有时,会在其原型对象上找,其原型对象没用时,会再其原型对象的原型对象上找;
使用原型对象注意点
- 当我们改变构造函数的prototype的时候,需要重新设置constructor属性
//在Person.prototype.sayHi = function(){} 基础上进一步改进
Person.prototype = {
constructor:Person, //注意点
sayHi:function(){
console.log("hi")
}
}
var p1 = new Person('zs',18)
p1.sayHi()
- 先设置原型属性,再创建对象,才能访问原型对象的成员
原型对象的应用
拓展内置对象的功能,比如给array方法 增加一个求偶数的和的功能
var arr = [1,2,4,5]
Array.prototype.getSum = function(){
var sum = 0;
for (var i = 0;i < this.length; i++){
if(this[i] %2 === 0) {
sum += this[i]
}
}
return sum
}
//但是能不能用下面这种方法呢?
Array.prototype = {
getSum = function(){}
}
//答案是不能!因为Array,String 都属于内置对象,如果用以上方法,会覆盖掉他们本身的那些方法