一、Node.js “ 实体类 ” 的定义
// 定义类 Person 有参构造方法
function Person(name, sex, age, addr, salary) {
this.name = name;
this.sex = sex;
this.age = age;
this.addr = addr;
this.salary = salary;
}
二、定义 set 方法以设置 实体类 Person 的属性值
//set 方法
Person.prototype.setName=function (name) {
this.name=name;
};
Person.prototype.setSex=function (sex) {
this.sex=sex;
};
Person.prototype.setAge=function (age) {
this.age=age;
};
Person.prototype.setAddr=function (addr) {
this.addr=addr;
console.log(“Person setAddr”);
};
Person.prototype.setSalary=function (salary) {
this.salary=salary;
};
三、定义 get 方法以获取 实体类 Person 的属性值
//get 方法
Person.prototype.getName=function(){
return this.name;
};
Person.prototype.getSex=function(){
return this.sex;
};
Person.prototype.getAge=function(){
return this.age;
};
Person.prototype.getAddr=function(){
return this.addr;
};
Person.prototype.getSalary=function(){
return this.salary;
};
四、构造 Person 实例对象
// 使用 new 全参构造方法 获取实例对象
let Kirito=new Person(“ 桐人 ”,
“ 男 ”,
18,
“SAO”,
999999999);
// 控制台打印 Person 实例
console.log(Kirito);
console.log(“——————————————————-” + “\n\n”);
// 使用 get 方法 获取 Person 属性值
console.log(Kirito.getName());
console.log(Kirito.getSex());
console.log(Kirito.getAge());
console.log(Kirito.getAddr());
console.log(Kirito.getSalary());
console.log(“——————————————————-” + “\n\n”);
// 使用 new 无参构造方法 获取实例对象
let Ausua = new Person();
// 使用 set 方法 设置 Person 属性值
Ausua.setName(“ 亚丝娜 ”);
Ausua.setSex(“ 女 ”);
Ausua.setAge(18);
Ausua.setAddr(“SAO”);
Ausua.setSalary(999999999);
// 控制台打印 Person 实例
console.log(Ausua);
console.log(“——————————————————-” + “\n\n”);
五、Node.js 实例化的函数调用 工作流程
//Node.js 实例化的函数调用 工作流程
//let person =new Person(); 流程
// 每一个函数对象都有自己的 prototype 对象 : function Person()有自己的 prototype 对象
// 这个 prototype 对象是一个字典表 可以定义自己的方法 : Person.prototype.set/get 方法的定义
// 把这个函数对象看做一个类 使用 new 来创建类的实例
// 这个实例产生时 key—>__proto__
// 将函数的 prototype 浅复制 至实例中 作为 value
// 这样就建立了__proto__ : prototype 关联关系
// 实例创建完成后 绑定到这个函数的 this 里面
// 在后续的函数调用过程中 这个实例通过 this 进行传递
//this 传递的实例在函数的方法体中进行一系列初始化等运算
// 创建完实例,通过实例进行调用函数,其顺序是:先找自己方法体中的字典表,在去__proto__里面找
// 实现在类中定义好了 key—value 与函数方法后 再 new 出来的实例对象也具备相同的方法
// 我们可以通过调用这些函数方法来进行对类对象、属性的一系列操作
console.log(“——————————————————-” + “\n\n”);
六、Node.js 继承的实现
//Node.js extends
console.log(“ 继承 ”);
let Lady=function(){};
// 继承方式:
//1、不可用
//Lady.prototype=Person.prototype;
// 这 2 个 prototype 指向了同一个对象 若扩充 Lady 的方法 Person 也会随之更改
//2、在原来基类的 prototype 上进行浅复制
let Super= function(){};
Super.prototype=Person.prototype;
Lady.prototype=new Super();
// 定义子类 Lady 新的方法
Lady.prototype.setHobby=function(hobby){
this.hobby=hobby;
};
Lady.prototype.getHobby=function(){
return this.hobby;
};
// 实例化子类 Lady 对象 lady
let lady= new Lady();
// 设置子类继承的属性
lady.setName(“Illyasviel”);
lady.setSex(“ 女 ”);
lady.setAge(18);
lady.setAddr(“Fate”);
lady.setSalary(999999999);
// 设置子类特有的属性
lady.setHobby(“Kiss you GoodBye”);
console.log(lady);
console.log(“——————————————————-” + “\n\n”);
//3、使用 util.inherits 实现集成
let util =require(“util”);
// 定义子类 Student
let Student =function(cno,cname){
this.cno=cno;
this.cname =cname;
};
// 子类属性对应的 set get 方法
Student.prototype.setCno=function(cno){
this.cno=cno;
};
Student.prototype.setCname=function(cname){
this.cname=cname;
};
Student.prototype.getCno=function(){
return this.cno;
};
Student.prototype.setCname=function(){
return this.cname;
};
// 继承 Person
util.inherits(Student,Person);
let student =new Student(1,” 动漫一班 ”);
student.setName(“Sakura”);
student.setSex(“ 女 ”);
student.setAge(18);
student.setAddr(“Fate”);
student.setSalary(999999999);
console.log(student);
console.log(“——————————————————-” + “\n\n”);
七、方法的重写
// 方法的重写
console.log(“ 方法的重写 —override”);
//lady 的 prototype 中 setAddr 函数
//key:setAddr 没变 但是 value:setAddr 的 function 已经改变
// 覆盖掉原 Person.prototype.setAddr
Lady.prototype.setAddr=function(addr){
this.hobby=addr;
console.log(“override setAddr”);
};
lady.setAddr(“Fate Stay Night”);
console.log(“——————————————————-” + “\n\n”);
// 如方法重写后要调用基类 Person 的 setAddr 那么需要显示传递 this
console.log(“ 方法重写后调用基类 Person 的 setAddr”);
Lady.prototype.setAddr=function(addr){
Person.prototype.setAddr.call(this);
};
lady.setAddr(“Fate/Zero”);
八、总结与思考
// 总结与思考:
//
// 因为 Node.js 中没有 Java 等高级语言中 class 类的概念 故出现了__proto__ 与 prototype
// 与 java 相比 其两者的关系类似于继承:
// 函数创建时,Node.js 会为这个函数自动添加 prototype 属性,值是空的字典表对象 {}
// 在 let person=new Person(); 时,此时 function Person(){} 就是一个构造函数(constructor)
// 那么 JS 就会帮你创建该构造函数的实例
// 该实例 会继承 构造函数内 已定义的 prototype 指向的所有属性和方法
// 该实例 通过 设置自己的__proto__ 指向构造函数的 prototype 来实现这种继承
// Node.js 通过__proto__和 prototype 的合作实现了原型链、对象的继承
// Node.js 是单继承的,Object.prototype 是原型链的顶端,类似于 Java 的 Object 类
// 构造函数,通过 prototype 来存储要共享的属性和方法,也可以设置 prototype 指向现存的对象来继承该对象
// 对象的__proto__指向自己构造函数的 prototype
// console.log(Ausua.__proto__==Person.prototype); 返回 true
// 注意:prototype 函数的内置属性 显示修改对象的原型的属性
// __proto__ 实例对象的内置属性 JS 内部使用寻找原型链的属性
// ES 规范定义对象字面量的原型就是 Object.prototype
// 最后
// 引用《JavaScript 权威指南》的一段描述:
// Every JavaScript object has a second JavaScript object (or null , but this is rare) associated with it.
// This second object is known as a prototype, and the first object inherits properties from the prototype.