一.面向对象编程
面向对象编程 OOP (Object Oriented Programming)。
- 面向对象是把事务分解成为一个个对象,然后由对象之间分工与合作。
- 在面向对象程序开发思想中,每一个对象都是功能中心,具有明确分工。
- 面向对象编程具有灵活、代码可复用、容易维护和开发的优点。
- 具有封装、继承、多态性的特性。
二.对象的创建方式
- 利用对象字面量创建对象 {}
var stu1 = {
name: "zhangsan",
age: 18,
sayHello: function () {
console.log(this.name);
}
}
// 弊端:代码冗余
- 利用 new Object 创建对象
var stu1 = new Object();
stu1.name = "jiangdachen";
stu1.age = 20;
stu1.sayHello = function () {
console.log(this.name);
}
var stu2 = new Object();
// 弊端:代码冗余
- 利用工厂函数创建对象
- 前两种创建对象的方法需要重复大量相同的代码,工厂模式创建对象就是为了解决这个问题。但它也是有弊端的,那就是无法判断对象属于哪一个类型。
function createObj(name, age) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.sayHello = function () { /
console.log(obj.name);
}
return obj;
}
var stu1 = createObj("john1", 21);
- 利用自定义构造函数创建对象
- 构造函数:是一个普通函数,当它和ncew运算符一起使用时,我们称之为构造函数,构造函数的首字母大写
// function 构造函数名() {
// this.属性 = 值;
// this.方法 = function() {}
// }
// new 构造函数名();
function Star(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(song) {
console.log(song);
}
}
//调用时,必须用new
var zs = new Star('张三', 18, '男');
zs.sing('爱~');
- 弊端:每个实例调用的方法应该是一致的,但是实际上在生成实例时,各自都创建了自己的方法。消耗了内存。
- ps:
new关键字执行过程:
1.new 构造函数可以在内存中创建了一个空的对象
2.this 就会指向刚才创建的空对象
3.执行构造函数里面的代码 给这个空对象添加属性和方法
4.返回这个对象
5.利用原型对象创建对象
具体的关于原型的内容,看下文内容。
function Person() {
}
Person.prototype.name = "john";
Person.prototype.age = 20;
Person.prototypesayHello = function () {
console.log(this.name);
}
var person1 = new Person();
- 解决了多个实例相同的方法指向不一样的问题,但是无法添加自己的属性值。
- 组合创建
属性放到构造函数里,方法放到原型对象上
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function () { //原型方法
console.log(this.name); //this也是指向实例
}
var person1 = new Person("john1", 21)
三.原型对象与原型链
-
原型对象:每一个函数都有一个属性prototype,
称之为原型对象或者原型。原型是一个引用类型,
原型上的属性和方法能被实例访问。 -
实例对象原型:实例对象有一个属性 _ proto_ 指向构造函数的 prototype 原型对象。
-
实例对象原型_proto_和构造函数的prototype是等价的。
-
constructor :constructor 作为原型对象的一个默认属性存在,表示创建实例的构造函数的引用
function Foo() {
}
console.log(Fooprototype);
console.log(Foo.prototype.constructor);
-
原型链:每一个实例对象又有一个__proto__属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有__proto__属性,这样一层一层往上找就形成了原型链。
-
关系:
1.构造函数的prototype属性指向了构造函数原型对象。
2.实例对象是由构造函数创建的,实例对象的__proto__属性指向了构造函数的原型对象。
3.构造函数的原型对象的constructor属性指向了构造函数,实例对象的原型的constructor属性也指向了构造函数。 -
查找规则:当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。如果还没有就查找原型对象的原型(Object的原型对象)。依此类推一直找到 Object 为止(null),按照原型链的方式去查找。
// 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数
Star.prototype = {
constructor: Star,
sing: function() {
console.log('我会唱,跳');
},
movie: function() {
console.log('我会rap,篮球');
}
}
var zs = new Star('张三', 18);
var ls = new Star('李四', 19);
console.log(Star.prototype);
console.log(ldh.__proto__);
console.log(Star.prototype.constructor);
console.log(ldh.__proto__.constructor);
FnB.prototype = new FnC(); //让FnB原型对象具有c属性
var fb = new FnB();
console.log(fb.c); //cc
FnA.prototype = new FnB(); //让FnA原型对象里具有b属性
var fa = new FnA();
逆战班——sen