面向对象的基础生活中常见使用面向对象的例子:react、vue、组件、库
状态的问题,操作

对象 = 属性+方法

概念:
变量 - 属性、状态、数据
过程 - 方法、函数

类(class)

Date、String、Array…..

实例化、实例(instance)

使用 new 关键字
let oDate = new Date();
oDate就是一个实例

成员(member):

是统称,包括东西( 属性+方法 )
成员有:
实例成员:实例里面的成员
str.length、arr.push

类成员:

类里面的成员
Math.PI

实例成员和 类成员是不需要实例化

抽象:

第一个含义:
提取信息的过程,实现一系列功能的过程

第二种含义:
抽象类,并不能拿去用,它的作用提供一个公共的基类、父类,其他类都可以去继承他一些公共的方法

面向对象思想:

1.封装

目的为了让别人不能轻易去破坏你对象里面的属性和方法
保护对象里面的成员
数据的隐藏,必须通过方法修改
强制规定访问的权限
便于理解

2.继承

任何一个类可以不用从零写起,可以在原有类基础上做一些修改和添加,形成一个新的类
目的:
为了重用代码
无需去修改父类
多重继承:每个类可以有多个父类,js、java不支持,c++支持,会让结构比较混乱
抽象类:

3.多态

其实是一种抽象
简化问题

设计模式

前人的经验
每一个模式,可对应解决实际生活中的问题
重点是:如何设计一个对象,应该有哪些属性和方法

面向对象写法:

常见写法:
旧版本(es6前)

  1. // ES5写法
  2. // 即是构造函数 也是类
  3. function A() {
  4. this.name = 'summer';
  5. this.age = 18;
  6. }
  7. // 需要额外的prototype 添加方法
  8. A.prototype.show = function() {
  9. console.log(this.name+','+this.age);
  10. }
  11. const a = new A();
  12. a.show();

新版写法(es6后)

  1. // 类
  2. class B{
  3. constructor(name, age) {
  4. // 构造函数、构造器
  5. this.name = name;
  6. this.age = age;
  7. }
  8. show() {
  9. console.log(this.name+','+this.age);
  10. }
  11. }
  12. const b = new B('jack', 24);
  13. const c = new B('lucy', 20);
  14. b.show();
  15. c.show();

类型检测

typeof
适合检测基本类型
number、boolean、string、function、object、undefined

instanceof
检测对象类型
检测实例的具体类型,对子级类型有反应、对父类类型也有也有反应
从继承来说,子类 >= 父类,子类包含父类的属性和方法

constructor
不常用
作用可以帮助返回实例的构造器,
精确类型判断,只包括子级、不包括父级

  1. let a = 1;
  2. let b = [1, 2];
  3. let c = {a: 'ss'};
  4. const f = () => {console.log('ddd');};
  5. console.log(typeof a); // number
  6. console.log(typeof b); // object
  7. console.log(typeof c); // object
  8. console.log(typeof f); // function
  9. console.log(typeof undefined); // undefined
  10. console.log('---------------------');
  11. // 检测是哪种对象
  12. console.log(b instanceof Array);
  13. console.log(b.constructor);
  14. console.log(c instanceof Object);
  15. console.log(c.constructor);
  16. console.log('---------------------');
  17. class User extends Array{
  18. }
  19. let d = new User();
  20. console.log(d instanceof Array); // true
  21. console.log('-----------------');
  22. let o = new Date();
  23. console.log('o', o.constructor === Date); // ƒ Date()
  24. // 如何判断节点类型
  25. const div1 = document.getElementById('div1');
  26. console.log(div1.constructor); // ƒ HTMLDivElement()
  27. console.log(div1 instanceof HTMLDivElement); // true

设计一个类 思路

1.自上而下
功能:类需要哪些功能
方法,属性
编码
类不断修改

2.尽早定位
assert - throw new Error();

  1. // 定义一个公用 断言函数,供类型检测时使用
  2. function assert(reg, msg){
  3. if(!reg) {
  4. throw new Error(msg);
  5. }
  6. }

3.注意
属性不要直接暴露
渲染 - 不要重新渲染

  1. /*
  2. 练习 设计一个简单的列表类
  3. 1.修改标题 setTitle、getTitle
  4. 2.设置列表的数据 setData、getData,一般有set,最好有个对应的get
  5. 3.重新渲染数据 render
  6. */
  7. class HotList {
  8. constructor(parent, title = '', data = []) {
  9. // 参数 必须 类型检测
  10. assert(parent, '必须有父级');
  11. assert(typeof title === 'string', '标题必须为字符串');
  12. assert(data instanceof Array, 'data必须为数组');
  13. this.parent = parent;
  14. // 问题1:直接把数据暴露在外面 后期优化
  15. this.title = title;
  16. // 数据类型检测
  17. this.data = data;
  18. }
  19. setTitle(title){
  20. this.title = title;
  21. }
  22. getTitle() {
  23. return this.title;
  24. }
  25. setData(data){
  26. this.data = data;
  27. }
  28. getData() {
  29. return this.data;
  30. }
  31. // 目前需要手动渲染 后期优化
  32. render() {
  33. data.forEach(v => {
  34. const div = document.createElement('div');
  35. div.setAttribute('class', 'item');
  36. div.innerHTML = `<div class='title'>${v.title}</div><div class='detail'>${v.detail}</div><div class="author">${v.author}</div>`;
  37. parent.appendChild(div);
  38. })
  39. }
  40. }
  41. const parent = document.getElementById('hotList');
  42. const data = [
  43. {
  44. title: '数据今生今世',
  45. detail: '独家独家独家独家',
  46. author: '定海村'
  47. },
  48. {
  49. title: '节省时间',
  50. detail: '的独家独家独家独家经典',
  51. author: '大口袋'
  52. },
  53. {
  54. title: '数据今生今世',
  55. detail: '独家独家独家独家',
  56. author: '定海村'
  57. },
  58. {
  59. title: '节省时间',
  60. detail: '的独家独家独家独家经典',
  61. author: '大口袋'
  62. }
  63. ];
  64. const list = new HotList(parent, '热门新闻', data);
  65. list.render();

原型 - prototype

1.作用
给类 添加/修改东西
这个类所有的实例都有这个东西

2.原理
实例需要某个东西(属性、方法),
首先从自己身上找,如果有直接用
如果没有 继续去类身上找
如果还没有 去父类身上找,直到找到为止,如果最终没找到 返回 undefined

  1. const arr1 = ['1', '2'];
  2. const arr2 = ['1', '2'];
  3. arr1.a = 'test';
  4. Array.prototype.a = 'abc';
  5. console.log(arr1.a); // test
  6. console.log(arr2.a); // abc

3.用途
给类添加方法
i. 添加公用的方法

  1. let str = 'ahdhgagsaagdga';
  2. String.prototype.countA = function() {
  3. return this.match(/a/g).length;
  4. }
  5. console.log(str.countA());
  1. <br /> ii. 修补系统的函数功能 - polyfill
  1. // 例如,IE7不支持 map,自己重写
  2. Array.prototype.map = function(cb) {
  3. const result = [];
  4. for(let i = 0; i < this.length; i++) {
  5. result.push(cb(this[i], i));
  6. }
  7. return result;
  8. }
  9. let arr = [1, 2, 3];
  10. let arr2 = arr.map((v,i) => v*3);
  11. console.log(arr2);

课后作业

数组做 polyfill
filter

  1. // 功能实现
  2. // 功能编写顺序要写在调用他 之前
  3. Array.prototype.filter = function(cb) {
  4. const result = [];
  5. for(let i = 0; i < this.length; i++) {
  6. if(cb(this[i], i)) {
  7. result.push(this[i]);
  8. }
  9. }
  10. return result;
  11. }
  12. const a = [1, 3, 5, 8, 2, 7, 10, 56, 39];
  13. // 过滤出偶数
  14. const b = a.filter((v, i) => v%2 === 0); // [8, 2, 10, 56]

reduce

  1. // 功能实现
  2. Array.prototype.reduce = function(cb, accumulator) {
  3. // 如果没有提供 初始值,则 collection(集合)中的第一个元素作为初始值
  4. if(this.length === 0) return;
  5. let result, i;
  6. if(accumulator === undefined) {
  7. result = this[0];
  8. i = 1;
  9. } else {
  10. result = accumulator;
  11. i = 0;
  12. }
  13. while(i < this.length) {
  14. result = cb(result, this[i]);
  15. i++;
  16. }
  17. return result;
  18. }
  19. const a = [1, 6, 2, 3, 3, 2];
  20. // reduce 求数组和
  21. console.log(a.reduce((prev, cur, index, arr) => prev + cur)); // 17
  22. // reduce 求数组最大值
  23. console.log(a.reduce((prev, cur, index, arr) => prev > cur ? prev : cur)); // 6
  24. // reduce 数组去重
  25. console.log(a.reduce((prev, cur, index, arr) => {
  26. prev.indexOf(cur) === -1 && prev.push(cur);
  27. return prev;
  28. }, []));
  29. // [1, 6, 2, 3]

Array.from
用于将两类对象转为真正的数组
类似数组的对象(array-like object)和可遍历(iterable)的对象

  1. // 功能实现
  2. Array.from = function(arrayLike) {
  3. const result = [];
  4. if(typeof arrayLike.length === 'number') {
  5. for(let i = 0; i < arrayLike.length; i++) {
  6. result.push(arrayLike[i]);
  7. }
  8. }
  9. return result;
  10. }
  11. console.log(Array.from('hello')); // ["h", "e", "l", "l", "o"]
  12. const arraylike = {
  13. '0': 'jsjs',
  14. '1': 'dk',
  15. '2': 'uhdhd',
  16. length: 3
  17. };
  18. console.log(Array.from(arraylike)); // ["jsjs", "dk", "uhdhd"]

String.trim()

  1. // 功能实现
  2. String.prototype.trim = function() {
  3. let newStr = '';
  4. let startIndex, endIndex;
  5. for(let m = 0; m < this.length; m++) {
  6. if(this.charAt(m) !== " "){
  7. startIndex = m;
  8. break;
  9. }
  10. }
  11. for(let n = this.length - 1; n > 0; n--) {
  12. if(this.charAt(n) !== " "){
  13. endIndex = n;
  14. break;
  15. }
  16. }
  17. console.log(startIndex, endIndex);
  18. for(let i = startIndex; i <= endIndex; i++) {
  19. newStr = newStr+this.charAt(i);
  20. }
  21. return newStr;
  22. }
  23. // 正则实现
  24. String.prototype.trim = function () {
  25. return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  26. };

3.豆瓣弹出层,选择频道
i. 点击频道名称,豆瓣弹出层
ii. 点击页面任意位置,弹出层消失
iii. 弹出层中的数据需要是动态的
iv. 弹出层选择后 ,频道名称变了

  1. // 功能实现