JS高级之面向对象
-
什么是面向对象
面向对象主要是将一个物体的属性和功能进行封装成一个大的类别,然后通过实例化创建出对象, -
创建对象的方式
2.1 字面量 2.2 function的构造函数 2.3 通过class,创建类
//1.字面量
var girlFriend = {
name: 'hanmeimei',
age: 21,
height: 170,
say: function () {
console.log("你好,我是" + this.name )
}
}
girlFriend.say()//你好,我是hanmeimei
//通过字面量的方式创建了一个女朋友的对象
//2.构造函数
function GirlFriend(uname,age){
this.name = uname;
this.age = age;
this.say = function(){
console.log("你好,我是"+this.name);
}
}
var hanmeimei = new GirlFriend('hanmeimei',18)
hanmeimei.say()//你好,我是hanmeimei
//3.通过类的方式
class GirlFriend {
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
say() {
console.log("你好,我是" + this.uname);
}
}
var hanmeimei = new GirlFriend('hanmeimei', 18)
hanmeimei.say()//你好,我是hanmeimei
- 通过class是怎么创建的对象
//创建一个名叫女朋友的类 class GirlFriend { //通过new传递实参,在construction中接受实参 constructor(uname, age) { //创建一个uname和age的属性,并进行赋值 this.uname = uname; this.age = age; } //在这个类中有一个共同的方法say() say() { console.log("你好,我是" + this.uname); } } //将实例化对象返回 var hanmeimei = new GirlFriend('hanmeimei', 18) //调用hanmeimei里面的say方法 hanmeimei.say()//你好,我是hanmeimei console.log(hanmeimei);//GirlFriend {uname: 'hanmeimei', age: 18}
在创建的过程中,做了那些事情
重点:
1.通过new创建了一个空的对象
2.this指向这块内存区域
3.通过this进行添加属性并赋值
4.创建完成之后由hanmeimei这个变量指向创建的这个实例对象
4.类的继承
基本语法
class Father{
}
class Son extends Father{
}
实例代码
class Father {
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
getMoney() {
console.log(this.uname + '在赚钱');
}
}
class Son extends Father {
constructor(uname, age) {
//调用父类的构造方法
super(uname, age)
}
}
var xiaoming = new Son('小明', 20);
//按理来说,在创建小明上并没有一个getMoney,
//但是Son(长大了)通过extends关键字继承了Father中的getMoney
xiaoming.getMoney()//小明在赚钱
5.静态成员和实例成员
function GirlFriend(uname, age) {
this.name = uname;
this.age = age;
this.say = function () {
console.log("你好,我是" + this.name);
}
}
var hanmeimei = new GirlFriend('hanmeimei', 18)
// 静态属性
GirlFriend.sex = '女'
//静态属性只能通过构造函数.属性名
console.log(GirlFriend.sex);//女
//动态属性
hanmeimei.height = 170
//undefined,静态属性不能访问动态属性的方法,同理,动态属性不能够访问静态属性的方法
console.log(GirlFriend.height);
console.log(hanmeimei.sex);//undefined,静态属性不能访问动态属性的方法,同理,动态属性不能够访问静态属性的方法
console.log(hanmeimei.height);//170
总结:动态属性只能通过构造函数访问,静态属性只能通过实例对象访问
6.构造函数的问题
function GirlFriend(uname, age) {
this.name = uname;
this.age = age;
this.say = function () {
console.log("你好,我是" + this.name);
}
}
var hanmeimei = new GirlFriend('hanmeimei', 18)
var xiaoli = new GirlFriend('xiaoli',20)
hanmeimei.say();//你好,我是hanmeimei
xiaoli.say()//你好,我是xiaoli
通过画图来理解:在构造函数中this指向的创建出来的实例对象,所以在每次创建一个对象都会创建一个say方法,而每个say都是独立且相同的
问题:如果创建100个对象就会创建100个say的内存空间,但每个say都一样,会消耗内存
更改:问题找到了,该怎么解决?我们应该将这个共有的方法存放在构造函数的原型对象上,实现数据共享
function GirlFriend(uname, age) {
this.name = uname;
this.age = age;
}
console.log("----------------------------")
GirlFriend.prototype.say = function () {
console.log("你好,我是" + this.name);
}
console.log("----------------------------")
var hanmeimei = new GirlFriend('hanmeimei', 18)
var xiaoli = new GirlFriend('xiaoli',20)
hanmeimei.say();//你好,我是hanmeimei
xiaoli.say()//你好,我是xiaoli
//那么通过这句话就能实现?那不得来验证下
//这句话打印的hanmeimei这个实例对象的隐式原型和xiaoli的隐式原型
console.log(hanmeimei.__proto__===xiaoli.__proto__);//true
通过画图来理解:
怎么理解这幅图呢?
首先有一个构造函数,每个构造函数中都会有prototype原型对象这么一个东西,并且是个对象类型,所以会开辟一块新的内存用来存储构造函数的原型对象
然后,通过对象实例化,在实例化后,会发现里面有个__proto__对象的原型,指向构造函数的原型对象,就可以实现数据共享的操作
7.原型链
当访问一个对象的属性和方法是,会现在自身中寻找,找不到就通过__proto__找到创建这个实例对象的构造函数的原型对象,如果还没有找到,就会在网上找创建出这个构造函数的构造函数的原型对象,一直反复直到顶层,而这个查找过程就是原型链