Javascript是一种基于对象(object-based)的语言,但它没有类的概念,如果我们要把”属性”(property)和”方法”(method),封装成一个对象,甚至要从原型对象生成一个实例对象,我们有以下多中方式
1. 最简单的方式创建一个对象
// 1. 创建一个对象
var person=new Object();
person.name="czj";
person.getName=function(){
console.log(this.name);
}
person.getName(); // czj
- 缺点:使用同一个接口创建很多对象,会产生大量的重复代码
2. 工厂模式
// 2. 工厂模式
function CreatePerson(name,job){
var obj=new Object(); // 原料
obj.name=name; // 加工
obj.job=job;
obj.getName=function(){
console.log(this.name);
}
return obj; // 出厂
}
var p1=CreatePerson('czj',25);
p1.getName(); // czj
var p2=CreatePerson('fz',24);
p2.getName(); // fz
console.log(p2 instanceof Object);// Object
- 缺点:无法识别对象的类型
3. 构造函数模式
// 3. 构造函数模式
function Person(name,age){
this.name=name;
this.age=age;
this.getName=function(){
console.log(this.name);
}
}
var p1=new Person('czj',25);
p1.getName(); // czj
var p2=new Person('fz',24);
p2.getName(); // fz
- 构造函数名,首字母大写
- 要创建Person实例,必须使用new操作符,那么
new
操作符做了什么,看下面一个函数
/ new 操作符 创建实例
function Person(name,age){
var obj={}; // 1. 创建一个对象
Person.apply(obj);; // 2. 使this指向obj
obj.__proto__=Person.prototype; // 3. 把对象的__proto__属性指向Person的原型对象
this.name=name; // 4. 为这个对象添加属性、方法
this.age=age;;
this.getName=function(){
console.log(this.name);
};
return obj; // 5. 返回对象
}
- 构造函数的缺点:每个方法都要在每个实例上创建一遍
console.log(p1.getName == p2.getName); //false
4. 构造函数模式 + 原型模式
- 构造函数模式用于定义`实例属性,原型模式用于定义方法和共享的属性
- 每个函数都有一个
prototype
属性,指向函数的原型对象 - 当调用构造函数创建一个 新实例 后, 实例内部 有一个指针
_ proto _
指向 构造函数的 原型对象 - 所以 实例通过
_ proto _
属性,就可以拥有原型对象上的属性和方法 - 这个连接存在与实例和构造函数的原型对象之间
1)第一种方式:
function Person(name){
this.name=name;
}
Person.prototype.getName=function(){
console.log(this.name);
}
var p1=new Person('czj');
p1.getName(); // czj
var p2=new Person('fz');
p2.getName(); // fz
console.log(p1.getName == p2.getName); // true
console.log(p1.__proto__);
2)第二种方式: 使用对象字面量 ( 需要手动添加constructor
属性 )
// 对象字面量的方式
function Student(name,age){
this.name=name;
this.age=age;
}
Student.prototype={
constructor:Student, // 相当于重写了prototype , 需要手动添加constructor属性
job:'student', // 共享的属性
getName:function(){
console.log(this.name);
},
getAge:function(){
console.log(this.age);
},
getJob:function(){
console.log(this.job);
}
};
var s1=new Student('czj',25);
s1.getJob(); // student
var s2=new Student('fz',24);
s2.getJob(); // student
console.log(Student.prototype.constructor);// Student
protype 模式的验证方法
isPrototypeOf() :用于判断某个
prototype
对象和某个实例之间的关系console.log(Student.prototype.isPrototypeOf(s1)); // true console.log(Student.prototype.isPrototypeOf(s2)); // true
hasOwnProperty():用于检测一个属性是存在与实例中,还是存在于原型中
console.log(s1.hasOwnProperty('job')); // false console.log(s1.hasOwnProperty('name')); // true
in运算符
in
运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。console.log('name' in s1); // true console.log('job' in s1); // true
in
运算符还可以用来遍历某个对象的所有属性。for(var prop in s1){ console.log(prop); };