笔记 javascript 面向对象
对象创建与访问
new关键词创建对象
var obj=new Object();
字面量形式
var obj={};
对象访问
person.name
person["name"];
构造函数与原型
构造函数与普通函数并无区别,首字母大写是一种约定,用来表示这是一个构造函数。但是new关键词的存在,让构造函数变得与众不同。构造函数中的this与原型方法中的this(实例调用方法时)指向的都是当前的实例。
//构造函数
var Person=function(name,age){
this.name=name;
this.age=age;
}
//Person.prototype为Person的原型
Person.prototype.gerName=function(){
return this.name;
}
当我们使用Person对象创建一个具体的"人"时,我们称这个被创建的"人"为一个实例。
var p=new Person("Tom",20);
具体某一个人的特定属性,通常放在构造函数中;所有人公共的属性和方法,通常放在原型对象中。
模拟new关键词
//将构造函数一参数形式传入
function New(func){
//声明一个中间对象,该对象为最终返回的实例
var res={};
if(func.prototype !==null){
//将构造函数的实例指向构造函数的原型
res.__proto__=func.prototype;
}
//ret为构造函数的执行结果,这里通过apply将构造函数
//内部的this指向参数res,即实例对象
var ret=func.apply(res,Array.prototype.slice.call(arguments,1));
//当我们在构造函数中明确指定了返回对象时,那么new的
//执行结果就是该返回对象
if((typeof==="object" || typeof ret==="function") && ret !== null){
return ret;
}
//如果没有明确指定返回对象,则默认返回res,这个res就是实例对象
return res;
}
通过New方法的封装,new关键词在创建实例时经历了如下过程:
- 先创建一个新的、空的实例对象
- 将实例对象的原型指向构造函数的原型
- 将构造函数内部的this修改为指向实例
- 最后返回实例对象
构造函数、原型、实例之间的关系
构造函数的prototype,实例的__proto__都指向原型对象,原型对象的constructor指向构造函数。
构造函数中声明的变量与方法只属于当前实例,因此我们将构造函数中声明的属性与方法称为该实例的私有属性和方法,它们只能被当前实例访问;原型中的方法与属性能够被所有实例访问,因此我们将原型中声明的属性与方法称为公有属性与方法。
在构造函数中声明一个方法时,每创建一个实例,该方法都会被重新创建一次,而原型中的方法仅仅只会被创建一次。因此,在构造函数中声明私有属性和方法会消耗更多内存空间。
如果构造函数中声明的私有属性/方法与原型中公有属性/方法重名,会优先访问私有属性/方法
function Person(name){
this.name=name;
this.getName=function(){
return this.name+",你正在访问私有方法。"
}
}
Person.protoytpe.getName=function(){
return this.name;
}
var p1=new name("Tom",20);
p1.getName(); //Tom,你正在访问私有方法
可以用in来判断一个对象是否拥有某一个方法/属性,因此我们常使用in判断当前页面所处环境是否在移动端。
//续上例中创建的p1实例
console.log("name" in p1); //true
//只有在移动端才支持touchstart事件
var isMobile="ontouchstart" in document;
原型的其他写法
//写法1
function Person(){}
Person.prototype.getName=function(){}
Person.prototype.getAge=function(){}
Person.prototype.sayHello=function(){}
//对象字面量
Person.prototype={
constructor:Person;
getName:function(){}
getAge:function(){}
sayHello:function(){}
}
使用对象字面量能够简化写法,但需注意的是,当我们使用Person.prototype={}时,其实是将Person的原型指向了一个新的对象{}。如果不做特殊处理,将会导致原型对象丢失,因此在这个新对象中,需要将它的constructor属性指向构造函数Person,这样就重新建立了正确的对应关系。
原型链
实例方法、原型方法、静态方法
构造函数中的方法称为实例方法;通过prototype添加的方法称为原型方法;直接挂载在构造函数中的方法称为静态方法,因此静态方法不能通过实例访问,只能通过构造函数访问。静态方法又称为工具方法,常用来实现一些常用的,与具体实例无关的功能。
function Foo(){
this.bar=function(){
return "bar in Foo"; //实例方法
}
}
Foo.bar=function(){
return "bar in static"; //静态方法
}
Foo.prototype.bar=function(){
return "bar in prototype"; //原型方法
}