概念:如何进行理解JS中的面向对象
最基本的 OOP 思想就是我们想要在我们的程序中使用对象来表示现实世界模型,并提供一个简单的方式来访问它的功能,否则很难甚至不能实现.
对象可以包含相关的数据和代码,这些代表现实世界模型的一些信息或者功能,或者它特有的一些行为.
对于一个人(person)来说,我们能在他们身上获取到很多信息(他们的住址,身高,鞋码,基因图谱,护照信息,显著的性格特征等等),然而,我们仅仅需要他们的名字,年龄,性别,兴趣这些信息,然后,我们会基于他们的这些信息写一个简短的介绍关于他们自己,在最后我们还需要教会他们打招呼。以上的方式被称为抽象-为了我们编程的目标而利用事物的一些重要特性去把复杂的事物简单化。
比如对于人这个类来说,它具有各种基本属性和方法,人与人之间的区别只是属性的值不一样,这样我们就简单构造了一个类来描述真实的世界。
emmm简单点来进行理解的话,就是将现实的事物进行抽象化,通常就是名词,完后用相应的名词分解加上形容词去形容(也就是对象的属性)以及名词的动作通常是动词(也就是面向对象之中的方法),两者进行相结合来表达出对象的基本操作。我记得在面向对象思想当中有五句英文很好的概括了这点 ,emmm 下次加以补充说明。。。。好 进入今天的正题JS面向对象的理解。
JS的函数式编程体现面向对象:
function Person(first, last, age, gender,interests) {
this.name = {
first,
last
};
this.age = age;
this.gender = gender;
this.interests = interests;
}
注:此中的this与Java之中的this用法还是有很大区别的,这个在后续进行说明。暂且理解为window
例子程序2:
// 1、字面式的对象声明:最简单,好理解,推荐使用;
var person = {
name: "Jack",
age: 20,
eat: function () {
alert("人吃饭!");
}
};
person.addr = "上海"; // 给对象添加属性;
alert("name: " + person.name);
alert("age: " + person.age);
alert("addr: " + person.addr);
person.eat();
// 2、使用模拟类的方式创建对象:由于JS没有类,可以使用function模拟一个类;
// 模拟类中方法的声明有三种:(1)、类方法 (2)、原型方法 (3)、对象方法;
// 写法1:无参构造函数;又可分为 普通写法 和 原型写法;
function Person() {
}
// 普通写法:先实例化对象,再赋值;
// 用 new 关键字去实例化一个Person对象;
var stu = new Person();
stu.name = "Tom";
stu.age = 20;
stu.addr = "上海";
// (1)、类方法;
stu.eat = function () {
alert("我叫" + stu.name + ",我今年" + stu.age + "岁了,我住在" + stu.addr);
}
stu.eat();
// 原型写法:使用关键字 prototype;先赋初值,然后再实例化对象;
Person.prototype.name = "Ken";
Person.prototype.age = 33; // prototype:该属性使模拟类可以被添加属性和方法;
Person.prototype.addr = "苏州";
Person.prototype.eat = function () { // (2)、原型方法;
alert("我叫" + this.name + ",我今年" + this.age + "岁了,我住在" + this.addr);
}
var teacher = new Person();
teacher.eat();
// 写法2:有参构造函数;先给当前对象赋值,然后再实例化对象,赋初值;
function Person(name, age, addr) {
this._name = name; // this:当前对象;
this._age = age;
this._addr = addr;
this.eat = function () { // (3)、对象方法;
alert("我叫" + this._name + ",我今年" + this._age + "岁了,我住在" + this._addr);
}
Person.prototype.fly = function () { // (2)、原型方法;写在类里面;
alert("人类会飞!");
}
}
Person.prototype.run = function () { // (2)、原型方法;写在类外面;
alert("人类会跑步!");
}
var stu = new Person("Lucy", 22, "南京"); // 实例化一个Person对象,并赋初值;
stu.eat();
stu.fly();
stu.run();
// 3、JavaScript模拟类的封装; 封装语法:( function () { 类的主体 } () );
(function () {
function people(name, age) { // 声明一个类;
this._name = name;
this._age = age;
}
people.prototype.sayHello = function () { // 原型方法;
alert("People_Say: 我叫" + this._name + ", 我今年" + this._age + "岁了!");
}
window.People = people; // 必须将类放到最顶层的 window对象 上才能执行;
}());
var people = new People("Tom", "22"); // 实例化一个 People 对象;
people.sayHello();
// 4、继承;
// 封装一个子类(Student),继承于父类(People):
(function () {
function Student(name, age) {
this._name = name;
this._age = age;
}
Student.prototype = new People(); // 使student类继承于People类;
var stuSay = Student.prototype.sayHello; // 继承父类中的方法;
//var stuSay = Student.prototype.sayHello(); // 写成这种方式会直接执行父类中的方法;
// 子类重写父类的方法;
Student.prototype.sayHello = function () {
stuSay.call(this); // 重写之后,子类只会调用自己的方法;如果想调用父类的方法,可以使用该方式:
alert("Student_Say: 我叫" + this._name + ", 我今年" + this._age + "岁了!");
}
window.Student = Student; // 将 Student类 传给最顶层的 window 对象;
}());
var stu = new Student("小花", "18");
stu.sayHello();
// 5、空对象:用于承载类中的属性和方法,还可以用于类的继承;
function Father(name, age) { // 声明一个Person类;
var _this = {}; // 声明一个空对象,用来承载类中的属性和方法;
_this._name = name;
_this._age = age;
_this.sayHello = function () { // 对象方法;
alert("Father_say: 我叫" + _this._name + ", 我今年" + _this._age + "岁了!");
}
return _this; // 使用空对象承载属性和方法,最后必须 return _this;
}
var father = new Father("张三", "33");
father.sayHello();
// 声明一个子类:
function Son(name, age) {
var _this = Father(name, age); // 声明一个空对象,继承父类(Father);
_this._name = name;
_this._age = age;
var sonSay = _this.sayHello; // 继承父类的方法;
_this.sayHello = function () { // 子类重写父类的方法;
sonSay.call(this); // 调用父类的方法;
alert("Son_say: 我叫" + _this._name + ", 我今年" + _this._age + "岁了!");
}
return _this;
}
var son = new Son("小三", "11");
son.sayHello();
关于原型链的介绍:(后续有待更新)
(1)基本概念介绍:原型是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有”prototype”属性,函数对象有”prototype”属性,原型对象有”constructor”属性。
(2)基础概念理解:在JavaScript中,原型也是一个对象,通过原型可以实现对象的属性继承,JavaScript的对象中都包含了一个”[[Prototype]]”内部属性,这个属性所对应的就是该对象的原型。
“[[Prototype]]”作为对象的内部属性,是不能被直接访问的。所以为了方便查看一个对象的原型,Firefox和Chrome中提供了__proto__这个非标准(不是所有浏览器都支持)的访问器(ECMA引入了标准对象原型访问器”Object.getPrototype(object)”)。在JavaScript的原型对象中,还包含一个”constructor”属性,这个属性对应创建所有指向该原型的实例的构造函数。
(3)JS对象构造过程分解:
在JavaScript中,每个函数 都有一个prototype属性,当一个函数被用作构造函数来创建实例时,这个函数的prototype属性值会被作为原型赋值给所有对象实例(也就是设置 实例的__proto__
属性),也就是说,所有实例的原型引用的是函数的prototype属性。(只有函数对象才会有这个属性!
)
new 的过程分为三步
var p = new Person(‘张三’,20)
1 var p={}; 初始化一个对象p。
2. p.proto=Person.prototype;,将对象p的 proto 属性设置为 Person.prototype
3. Person.call(p,”张三”,20);调用构造函数Person来初始化p。