JavaScript面向对象
面向对象的概念:
- 两种编程思路: 函数式(过程式)、面向对象(OOP)
- 类 : 具有相同的属性和方法的一类对象的抽象
- 实例 :某一类当中的一个对象
- 对象: 具有属性和方法的具体的事物
面向对象的三大特点:
- 封装
- 继承
- 多态
继承的种种:
- 原型链继承——把子类的原型(prototype)设置成父类的一个实例,效果就是把父类的私有和共有变成子类的共有
``` /* 父类(基类) */ function Girl(name, age, sex) { this.name = name; this.age = age; this.sex = sex; this.hair = "长头发"; } Girl.prototype.chat = function () { console.log('hello world'); } /* 子类(派生类) */ function BeautifulGirl() { } // 把子类的原型设置为父类的一个实例 BeautifulGirl.prototype = new Girl(); var bg1 = new BeautifulGirl(); console.log(bg1.hair); bg1.chat(); var bg2 = new BeautifulGirl(); console.log(bg2.hair); ```
- 冒充对象继承——在子类的构造函数里边,把父类的构造函数当做普通函数执行,并且用call方法把里面的this指向改成子类的实例,效果是把父类的私有变成子类的私有
``` /* 父类(基类) */ function Girl(name, age, sex, hair) { this.name = name; this.age = age; this.sex = sex; this.hair = hair; } Girl.prototype.chat = function () { console.log('hello world'); } /* 子类(派生类) */ function BeautifulGirl(name, age, sex, hair, longleg) { Girl.call(this, name, age, sex, hair); /* 冒充对象继承 */ this.longleg = longleg; } var bg1 = new BeautifulGirl('真真', 18, '女', '大波浪', '大长腿'); console.log(bg1); ```
- 混合继承——原型链+冒充对象继承:父类的私有变成子类的私有,父类的公有变成子类的公有
``` /* 父类(基类) */ function Girl(name, age, sex) { this.name = name; this.age = age; this.sex = sex; this.hair = "长头发"; this.ary = [1, 2, 3]; } Girl.prototype.chat = function () { console.log('hello world'); } /* 子类(派生类) */ function BeautifulGirl() { } BeautifulGirl.prototype = new Girl(); var bg1 = new BeautifulGirl(); console.log(bg1.hair); bg1.ary[1] = 5; bg1.chat(); var bg2 = new BeautifulGirl(); console.log(bg2.hair); console.log(bg2.ary); ```
面向对象的创建:
- 普通模式——每次创建对象都要设置一遍属性,属性相同时,代码冗余;
``` var girl1 = { name: '如花', age: 18, sex: '女' ; var girl3 = new Object(); girl3.name = '春花'; girl3.age = 19; girl3.sex = '女'; ```
- 工厂模式——把创建对象和返回对象的功能封装在函数中,减少代码冗余,没有类的概念;
``` function girl(name, age, sex) { var obj = new Object(); /* 创建对象 */ obj.name = name; obj.age = age; obj.sex = sex; return obj; /* 返回对象 */ } var g1 = girl('如花', 18, '女'); console.log(g1); var g2 = girl('似玉', 18, '女'); console.log(g2); console.log(g1 instanceof girl); //false ```
- 构造函数模式——有类的概念,创建出来的实例是属于同一类,使用 instanceof 运算符可以检测出来,所有的属性和方法都是实例私有的;
- 1)-构造函数函数名首字母大写(规律) - 2)-用new 方式执行,new操作符会自动创建并返回对象,这个对象称之为这个类的实例 - 3)-构造函数里面的this指向当前实例 ``` function Girl(name, age, sex) { //自动创建对象 this.name = name; this.age = age; this.sex = sex; //自动返回对象 } var g1 = new Girl('如花', 18, '女'); var g2 = new Girl('似玉', 18, '女'); // Girl('如花', 18, '女'); //如果用普通函数方式执行,里面this指向window // console.log(window); ```
- 原型
- 所有对象天生自带一个属性 `__proto__`, 指向的是其构造函数的原型
- 所有的函数天生自带一个属性 `prototype`(原型)
- 原型+构造函数模式——即可以实现私有属性,也可以实现共有方法
``` function Girl(name, age, sex, str) { //自动创建对象 this.name = name; this.age = age; this.sex = sex; this.str = str; //自动返回对象 } Girl.prototype.chat = function () { // 公有方法里面的this指向当前调用它的实例 console.log(this.str + 'hahaha'); } var g1 = new Girl('如花', 18, '女', 'hello world'); g1.chat(); ```
- 动态混合模式——把共有方法放在构造函数里边
``` /* 动态混合模式 */ function Girl(name, age, str) { this.name = name; this.age = age; this.str = str; if (typeof chat != 'function') { //如果不存在chat方法,就添加 Girl.prototype.chat = function () { console.log(this.str); } } } var g1 = new Girl('小红', 18, 'hello world'); ```
this的指向:
- 在普通函数中,没有对象调用,this指向window;
- 在对象方法中,this指向调用它的对象;
- 在事件处理函数中,this指向触发事件的元素;
- 在构造函数中,this指向当前实例;
call和apply方法可以改变this的指向——使用方法参考:
var obj = { a: 10, b: 20 } function fn(c, d) { console.log(this.a + this.b + c + d); } //fn.call(obj, 30, 40); fn.apply(obj, [30, 40]); //apply的第二个参数是一个数组 fn.apply(null, [30, 40]); // 第一个参数传null,指向window ```
call()方法和apply()方法用法总结 - 菲比月 - 博客园 https://www.cnblogs.com/phoebeyue/p/9216514.html