一、首先来了解一下对象
对象是什么?
对象是包含相关属性和方法的集合体,有着属性和方法
什么是面向对象?
面向对象仅仅是一个概念或者编程思想
通过一种叫做原型的方式来实现面向对象编程
二、如何创建对象
这里有两种方式:
- 自定义对象
- 内置对象
先来看自定义对象
1、基于Object对象的方式创建对象
语法格式:
var 对象名称 = new Object();
代码示例:
var demo1=new Object();
demo1.name="王大锤";
demo1.age=18;
demo1.sex="男";
demo1.uses="是一个大汉";
demo1.showName=function(){ alert(this.name);
}
demo1.showName();
2、使用字面量赋值方式创建对象
语法格式跟上面的有点不同
具体来看代码:
var demo2={
name:"朱小明",
sex:"男",
age:"20",
uses:"是一个男人",
showName:function(){ alert(this.name);
}
}
flower.showName();
一般推荐用第二种方式
再来看常见的内置对象及方法属性
String(字符串)对象
- length属性
- indexOf()方法,replace()方法
- …
Math(算数)对象
- round方法
- max()方法
- min()方法
- …
Array(数组)对象
- length属性
- sort()方法
- concat()方法
- join()方法
- …
Boolean(逻辑对象)对象
- true与false
- toString()方法
Date(日期)对象
- get xxx:获取 年 月 日 时 分 秒等
- set xxx:设置 年 月 日 时 分 秒等
RegExp对象(正则表达式)
三、构造函数
使用构造函数可以使代码变得更简洁
大概步骤如下:
①创建一个新对象
②将构造函数的作用域赋给新对象(this就指向了这个新对象)
③ 执行构造函数中的代码
④返回新对象
直接来看代码
function Person(name,age,address){
this.name=name;
this.age=age;
this.address=address;
this.show=function(){
console.log("年龄"+this.name+"<br/>姓名"+this.age+"<br/>地址"+this.address)
}
this.test=function(){
console.log(this.name+"是个猪头"+"<br/>岁数:"+this.age+"<br/>身在地"+this.address)
}
}
var demo1 = Person("猪刚烈"+"88"+"高老庄");
var demo2 = Person("王大妈"+"100"+"华南海鲜市场");
demo1.show();
demo1.test();
demo2.show();
demo2.test();
四、继承
js并不是像java一样面向对象,而是基于对象,所以js是通过prototype的原型链继承
核心:将父类的实例作为子类的原型
这里讲三种常用方式:
- 原型链继承
- 借用构造函数实现继承
- 组合继承
原型链继承:
优点:
非常简便的实现了多重继承的关系;
能够确定原型和实例之间的关系;
缺点:
创建子类型实例时,无法向父类型传递参数,尤其是多重继承时,弊端非常明显;
所有的实例会共享通过原型链继承的属性,在一个实例中改变了,会在另一个实例中反映出来;
不能使用字面量添加新方法,会使继承关系中断(会重写constructor属性)
代码示例:
function Father() {
this.name = "父亲";
this.run = function () {
console.log(this.name + "开始跑步")
}
}
Father.prototype = {
constructor: Father, //自定义原型对象时,尽量重写constructor再指向该函数
hei: 200,
eat: function () {
console.log(this.name + "开始吃饭")
}
};
function Son(age) {
this.age = age;
this.sleep = function () {
console.log(this.name + "开始睡觉")
}
}
Son.prototype = new Father();
Son.prototype.constructor = Son;
Son.prototype.playGame = function () {
console.log(this.name + "开始玩游戏")
};
const son = new Son(10);
console.log(son.name); //父亲
console.log(son.age); //10
son.run(); //父亲开始跑步
son.eat(); //父亲开始吃饭
son.sleep(); //父亲开始睡觉
son.playGame(); //父亲开始玩游戏
基于原型链继承的查找方式是,如son.run()首先现在son对象内查找,没有找到则通过son.__proto__去Son.prototype原型链上查找,所以就进入到new Father()对象中查找,找到了所以就打印出父亲开始跑步,查找son.name是同样的步骤,当查找son.eat()时,在new Father()对象中没有找到,则又通过Father.__proto__去Father.prototype原型上查找找到了,所以就打印出父亲开始吃饭通过这种方式继承,只要父类新增公共属性或公共方法或原型属性和方法,子类都可以访问到,但不能给父类构造传递参数,这在原型链中是标准做法。要确保构造函数没有任何参数,也无法实现多继承。
借用构造函数实现继承:
核心:复制父类的实例属性和方法给子类对象,但不包括父类构造的原型对象
优点:
可以通过使用call可以在调用的时候向父类型传递参数。
缺点:
仅仅借用构造函数,方法都在构造函数中定义,就无法实现函数复用;
通过借用构造函数,在父类型原型中定义的方法也无法通过原型链暴露给子类型;
function Son(age) {
Father.call(this);
this.age = age;
this.sleep = function () {
console.log(this.name + "开始睡觉")
}
}
Son.prototype.playGame = function () {
console.log(this.name + "开始玩游戏")
};
const son = new Son(10);
console.log(son.name); //父亲
console.log(son.age); //10
console.log(son.hei); //undefined 因为无法调用Father原型上的属性
son.run(); //父亲开始跑步
// son.eat(); //会报错 因为无法调用Father原型上的方法
son.sleep(); //父亲开始睡觉
son.playGame(); //父亲开始玩游戏
组合继承:(原型链+call继承)
代码示例:
function Son(age) {
Father.call(this);
this.age = age;
this.sleep = function () {
console.log(this.name + "开始睡觉")
};
}
Son.prototype = new Father();
// Son.prototype = new Father().__proto__;
// Son.prototype = Father.prototype;
//让constructor再指向Son构造函数,否则会执行Father构造函数
Son.prototype.constructor = Son;
Son.prototype.playGame = function () {
console.log(this.name + "开始玩游戏")
};
const son = new Son(10);
console.log(son.name); //父亲
console.log(son.age); //10
console.log(son.hei); //200
son.run(); //父亲开始跑步
son.eat(); //父亲开始吃饭
son.sleep(); //父亲开始睡觉
son.playGame(); //父亲开始玩游戏