JavaScript-面向对象

面向对象

模块化

模块依赖于 <script> 标签中的 type="module"

`导出`
1.export default 默认导出(仅导出一个文件)
2.export 导出指定的类名或者方法名  as起别名
	import A,{obj,arr as arr1,abc} from "./js/A.js"
3. 没有export 文件没有导出任何内容的js,可以直接使用import加载进来就会执行
        	 import "./js/Main.js";


`导入`
1.import fn from "./js/a.js"	fn()
// 在一个js文件中 只能只有一个默认导出
//所以从"./js/a.js" 文件中导入 fn 这个默认模块  fn是自己起的名字,和模块中的名称可以不同
import lyf from "./js/a.js"		lyf()	与上面的作用一样

2.import {obj,arr,fn} from "./js/b.js"
起别名(防止重名)  // 从"./js/b.js"中导入obj,arr,fn1
      import { obj, arr as arr1,fn1} from "./js/b.js"
整体起别名 // 从"./js/b.js"中导入obj,arr,fn1
 	  import * as o from "./js/b.js";import o from "./js/c.js"; 本质与1方式一样

3.import fn,{obj,arr} from "./js/d.js";
  既有默认导出模块,又有多个导出模块
  导入时,需要将默认导出模块写在前面,后面使用,再导出多个模块

import "./js/a.js"; //这样导入的js,所有的变量和函数都是私有的,全局是不能调用
a.js
function fn() {
   console.log("aaa")
}
export default fn;

b.js
// 这个js要导出多个模块 每个模块的名字必须要起名
export var obj = { a: 1, b: 2 };
export var arr = [1, 2, 3];
export function fn1() {
   console.log("bbb")
}

c.js
var obj={a:1,b:2};
var arr=[1,2,3];
function fn1(){
    console.log("bbb");
}
export default {obj,arr,fn1};  //这里的本质与a.js一样

面向对象

基础知识点

实例化	通过new构造函数的方式产生

1.(抽象对于某一群体共性,方法总的集合)class创造的类型
			class 类名(第一个字母大写)
2.基类:所有类的最基础类别  js的基类是Object
3.父类和子类:(B类  继承  A)  (C类 继承 B)
			A类和B类 就是C类的父类  B类和C就是A类的子类
			A类是B类的父类  B类是C类的父类
4.超类:子类的父类叫超类  A类就是B类的超类  B类就是C类的超类
5.实例化对象:通过new构造函数的方式产生这个类别的对象
			new 类名()

重要知识点

`属性`:
1.静态属性:(只属于类  不属于个体)
		static 开头 
		静态属性中this指向当前类
         只能被类本身调用,实例化对象无法调用
2.实例化属性:
		this指向实例化对象 即会调用编程,this就指向谁
		
`方法`:
1.静态方法:
		在静态方法中无法直接调用实例化方法和实例化属性
         只能被类本身调用
		在静态方法中this指向当前类
		调用静态方法: 类名.方法()
2.实例化方法:
		实例化方法中this指向实例化对象
         调用实例化方法: this.方法()

`构造函数`:
		constructor(a,b){
                console.log("aa")
                构造函数里面的this指向实例化对象
            }
1) js中所有类的构造函数都叫做constructor 但是constructor指向类名
2) 构造函数中不能使用return,并且只有一个构造函数
3) 在js中是没有私有、受保护的概念,所以构造函数或者其他地方的属性方法都是暴漏在外,公有的属性和方法

`extends继承`
1.可以将被继承的类的所有实例化属性和方法全部都继承给新的类
2.静态方法和属性也会继承,修改父类的静态属性,子类的静态属性也会改变
3.继承一个类之后,必须在构造函数中最上面写入super()
	3.1 super:超类的构造函数,执行超类的构造函数
    3.2 原因:从当前函数中传递进去,通过super传递到父类的构造方法,重新赋值
4.重写父类的方法会覆盖父类中原本的方法
5.执行父类方法的同时 执行自己重写的方法

class 女性 extends 人类 {
            化妆品=10;
            constructor(name,age){
                // super就是人类的构造函数constructor 继承时,必须在构造函数的第一句使用super调用其超类的构造函数
                super(name,age,"女")
            }
            生孩子(){
                console.log(this.姓名+"生孩子")
            }
            // 覆盖超类的当前方法 override
            走路(){
            //   console.log("穿高跟鞋");
            // }
                
            走路(){
              console.log("穿高跟鞋");
            //有super就是执行超类的走路方法
              super.走路();
            }
        }

补充知识点

判断一个对象的构造类型  instanceof
A->B->C
      c1=new C();
      c1 instanceof C	判断c1是不是C的类 实例化对象
      c1 instanceof B	判断c1是不是A和B的子类实例化对象
      c1 instanceof A

案例 小球移动

1.过程式编程

 	  var div = document.querySelector(".div1>div");
      var x = 0;
      var y = 0;
      //设置小球在 x y轴上的移动速率
      var speedX = 10;
      var speedY = 10;
      setInterval(function () {
         //x y是小球每次移动到的位置
         x += speedX;
         y += speedY;
         // console.log(x,"x")
         // console.log(y,"y")

         //设置小球的范围
         //当小球要超出范围时  就让小球往反方向走
         if (y <= 0 || y > 450) speedY = - speedY;
         if (x <= 0 || x >= 1150) speedX = -speedX;

         //设置小球的水平和纵向样式
         //x y 一起就是小球移动的距离
         div.style.left = x + "px";
         div.style.top = y + "px"
      }, 16)

2.函数式编程

	  var divs
      init();
      function init() {
         //获取到所有的div
         divs = document.querySelectorAll(".div1>div");
         //遍历每一个div 给每一个dive设置数据
         for (var i = 0; i < divs.length; i++) {
            //(小球开始运动的位置)让小球开始运动的位置随机
            //不让小球在同一位置开始移动
            divs[i].x = Math.random() * 1150;
            divs[i].y = Math.random() * 450;
            //让小球开始移动的方向随机
            //若是给固定值 所有小球会向同一方向移动
            divs[i].speedX = ~~(Math.random() * 7 - 3) || 1;
            divs[i].speedY = ~~(Math.random() * 7 - 3) || 1;
         }
         setInterval(animation, 16);
      }

      function animation() {
         for (var i = 0; i < divs.length; i++) {
            //x y是小球每次移动到的位置
            divs[i].x += divs[i].speedX;
            divs[i].y += divs[i].speedY;

            //设置小球的范围
            //当小球要超出范围时  就让小球往反方向走
            if (divs[i].y <= 0 || divs[i].y > 450) divs[i].speedY = -divs[i].speedY;
            if (divs[i].x <= 0 || divs[i].x > 1150) divs[i].speedX = -divs[i].speedX;

            //设置当前小球的水平和纵向样式
            divs[i].style.left = divs[i].x + "px";
            divs[i].style.top = divs[i].y + "px"
         }
      }

3.伪面向对象编程

class Ball {
         x = 0;
         y = 0;
         speedX = ~~(Math.random() * 7) - 3 || 1;
         speedY = ~~(Math.random() * 7) - 3 || 1;
         elem;

         constructor() {
            //构造函数中this指向实例化对象
            this.elem = document.createElement("div");

            var div1 = document.querySelector(".div1")

            //把获取的当前div添加到div1中
            div1.appendChild(this.elem);

            //获取父元素的getBoundingClientRect方法
            //用来获取父元素的大小、位置信息
            var rect = div1.getBoundingClientRect();

            //让小球开始运动的位置随机
            //rect.width,rect.height 分别是div1的宽和高
            //this.elem.offsetWidth,this.elem.offsetHeight 分别是当前div自身的宽高
            this.x = Math.random() * (rect.width - this.elem.offsetWidth);
            this.y = Math.random() * (rect.height - this.elem.offsetHeight);

            //若使用setInterval的正常形式形成回调函数  会让其中的this指向window
            //所以要使用箭头函数  会让this指向函数外的this 即该类
            setInterval(() => this.animation(), 16);
         }

         animation() {
             //x y是小球每次移动到的位置
            this.x += this.speedX;
            this.y += this.speedY;

            var rect = document.querySelector(".div1").getBoundingClientRect();

            if (this.x < 0 || this.x > rect.width - this.elem.offsetWidth) this.speedX = -this.speedX;
            if (this.y < 0 || this.y > rect.height - this.elem.offsetHeight) this.speedY = -this.speedY;

            this.elem.style.left = this.x + "px";
            this.elem.style.top = this.y + "px"
         }
      }

      for (var i = 0; i < 150; i++) {
         var b = new Ball()
      }

4.面向对象编程

 class Ball {
         x = 0;
         y = 0;
         speedX = ~~(Math.random() * 7) - 3 || 1;
         speedY = ~~(Math.random() * 7) - 3 || 1;
         elem;
         rect;
         //设置一个初始值 小div的宽高
         w = 50;
         //设置一个set集合 让其中的值是唯一的
         static list = new Set();
         constructor() {
            this.elem = document.createElement("div");
            //在内部设置div的样式
            Object.assign(this.elem.style, {
               width: this.w + "px",
               height: this.w + "px",
               backgroundColor: "red",
               position: "absolute",
               borderRadius: "50%",
            });
            //把创建好的实例化对象放入集合中
            //即放入的是每一个创建好的div
            Ball.list.add(this)
         }
         appendTo(parent) {
            //判断传入的参数是不是字符串 若是字符串则获取
            if (typeof parent === "string") parent = document.querySelector(parent);
            //判断parent是否存在 且是否为HTML标签
            if (parent && parent instanceof HTMLElement) {
               //把div添加到div1中
               parent.appendChild(this.elem);
               //this.rect dom属性方式设置一个变量rect
               this.rect = parent.getBoundingClientRect();
               //让小球开始运动的位置随机
               this.x = Math.random() * (this.rect.width - this.w);
               this.y = Math.random() * (this.rect.height - this.w)

               //设置当前小球所在位置
               Object.assign(this.elem.style, {
                   left: this.x + "px",
                   top: this.y + "px",
                })
            }
         }
         update() {
            //x y是小球每次移动到的位置
            this.x += this.speedX;
            this.y += this.speedY;

            //如果父元素没有大小,位置就跳出
            if (!this.rect) return;

            if (this.x < 0 || this.x > this.rect.width - this.w) this.speedX = -this.speedX;
            if (this.y < 0 || this.y > this.rect.height - this.w) this.speedY = -this.speedY;

            this.elem.style.left = this.x + "px";
            this.elem.style.top = this.y + "px";
         }
         static update() {
            Ball.list.forEach(item => {
               //item 是每一个创建好的div
               //遍历 让每一个div调用实例化的update方法
               item.update();
            })
         }
      }

      //小球数量
      for (var i = 0; i < 30; i++) {
         //向appendTo函数中传入值
         //实例化的对象调用appendTo方法传入parent需要的值
         new Ball().appendTo(".div1")
      }
      setInterval(function () {
         //调用静态update方法
         Ball.update();
      }, 16)

多选框

<div class="div1"></div>
   <script type="module">
      import CheckBox from "./js/CheckBox1.js";
      var arr = ["游泳", "跑步", "唱歌", "跳舞"];
      arr.forEach(item => {
         //实例化对象
         //把数组组中的值传入到 构造函数中 即把获取的值给label
         var ck = new CheckBox(item);
         ck.appendTo(".div1");
      })
   </script>
export default class CheckBox {
   //需要的文本
   label;
   //需要的块
   elem;
   _checked = false;
   constructor(label) {
      //this指实例化的对象
      this.label = label;
      //创建块元素
      this.elem = document.createElement("div")
      //把文本和需要设置背景图的div放入块中
      this.elem.innerHTML = `<div class='icon'></div>
      <span class='title'>${label}</span>
      `
      //设置 背景图样式
      this.setStyle();

      //若是使用普通函数 会形成回调函数 导致this指向window
      //要让this指向实例化对象 所以使用箭头函数 让函数中this指向跟随父元素
      //设置 点击侦听事件
      this.elem.addEventListener("click", () => this.clickHandler());
      //设置 鼠标按下侦听事件
      this.elem.addEventListener("mousedown", e => e.preventDefault())
   }

   //实例化方法
   appendTo(parent) {
      //判断传入的参数是不是字符串
      if (typeof parent === "string")
         //是字符串 则通过字符串的内容获取
         parent = document.querySelector(parent)
      //判断parent是否为真且是否是HTML元素
      if (parent && parent instanceof HTMLElement) parent.appendChild(this.elem)
   }

   //点击事件(开关的作用)
   clickHandler() {
      //_checked为false 点击后为true
      //把点击后的值做为参数 放入setChecked函数
      this.setChecked(!this._checked);
      //让当前实例化的对象 调用dispatch方法
      this.dispatch();
   }

   //设置点击切换时的样式
   setChecked(value) {
      //把value赋值给this._checked
      //为true时被选中  为false时不被选中
      this._checked = value;
      this.setCheckedStyle();
   }

   //该函数作用:获取点击时背景图切换的样式
   setCheckedStyle() {
      Object.assign(this.elem.firstElementChild.style, {
      // 若this._checked 为真 则显示被选中的图片样式
      //否则显示未被选中的图片样式
backgroundPositionX: this._checked ? "-128px" : "-238px",
backgroundPositionY: this._checked ? "-126px" : "-37px"
      })
   }
   dispatch() {
      //创建一个事件对象
      var evt = new Event("change");
      evt.checked = this._checked;
      evt.ck = this;
      //将该事件 抛发给doucment(触发该事件)
      document.dispatchEvent(evt);
   }

   //设置 初始时的样式
   setStyle() {
      this.elem.style.position = "relative";
      Object.assign(this.elem.firstElementChild.style, {
         width: "14px",
         height: "14px",
         backgroundImage: "url(./img/new_icon.png)",
         backgroundPositionX: "-238px",
         backgroundPositionY: "-37px",
         float: "left",
         marginRight: "5px",
         position: "relative",
         top: "3px"
      })
   }
}

多选框(继承版)

<div class="div1"></div>
   <script type="module">
      import CheckBox from "./js/CheckBox.js";
      var arr = ["游泳", "跑步", "唱歌", "跳舞"];
      arr.forEach(item => {
         var ck = new CheckBox(item);
         ck.appendTo(".div1");

         //设置侦听事件  观察实例化对象的变化
         ck.addEventListener("change", changeHandler)
      })
      function changeHandler(e) {
         console.log(e);
      }
   </script>
//父类
export default class Component extends EventTarget {
   elem;
   constructor(type, className) {
      super();
      //从子类 接收type 此处为"div"
      this.elem = document.createElement(type);
      //如果有类名 则设置类名
      if (className) this.elem.className = className;
   }

   appendTo(parent) {
      if (typeof parent === "string") parent = document.querySelector(parent);
      if (parent && parent instanceof HTMLElement) parent.appendChild(this.elem);
      return parent;
   }
}
//子类
import Component from "./Component.js";
export default class CheckBox extends Component {
  label;
  _checked = false;
  constructor(label) {
    super("div");
    this.label = label;
    //this.elem 在父类中创建的div
    this.elem.innerHTML = `
    <div class='icon'></div>
    <span class='title'>${label}</span>
    `
    // console.log(this.elem)
    this.setStyle();
    this.elem.addEventListener("click", () => this.clickHandler());
    this.elem.addEventListener("mousedown", e => e.preventDefault())
  }
  clickHandler() {
    //开始时this._checked为false
    //点击之后this._checked为true 并让它作为setChecked函数的参数
    this.setChecked(!this._checked);
    //点击时 调用dispatch函数
    this.dispatch();
  }

  setChecked(value) {
    //第一次点击后 value 从上面获取参数为true 并重新赋值给this._checked
    this._checked = value;
    //调用setCheckedStyle 函数
    this.setCheckedStyle();
  }

  //设置点击‘按钮’的样式
  setCheckedStyle() {
    //this.elem.firstElementChild 在div中添加的类名为 icon的div
    Object.assign(this.elem.firstElementChild.style, {
      //第一次点击后this._checked 为true 显示为被选中的样式
      //当再次点击后this._checked 为false 显示为未被选中的样式
      backgroundPositionX: this._checked ? "-128px" : "-238px",
      backgroundPositionY: this._checked ? "-126px" : "-37px"
    })
  }

  //创建事件函数 用于外部观察实例化对象的变化
  dispatch() {
    var evt = new Event("change");
    evt.checked = this._checked;
    this.dispatchEvent(evt);
  }

  setStyle() {
    //给创建的div加定位
    this.elem.style.position = "relative";
    //设置类名为 icon的div的初始样式
    Object.assign(this.elem.firstElementChild.style, {
      width: "14px",
      height: "14px",
      backgroundImage: "url(./img/new_icon.png)",
      backgroundPositionX: "-238px",
      backgroundPositionY: "-37px",
      float: "left",
      marginRight: "5px",
      position: "relative",
      top: "3px"
    })
  }
}

单选框

 <div class="div1"></div>
   <script type="module">
      import Radio from "./js/Radio.js";
      var arr = ["男", "女"];
      arr.forEach(item => {
         //item -->label  
         //"sex" -->name
         var ck = new Radio(item, "sex");
         ck.appendTo(".div1");
         ck.addEventListener("change", changeHandler);
      })
      function changeHandler(e) {
         console.log(e)
      }

      var arr = ["0-3000", "3001-6000", "6001-10000", "10001-20000"];
      arr.forEach(item => {
         //item -->label  
         //"wage" -->name
         var ck = new Radio(item, "wage");
         ck.appendTo(".div1");
         ck.addEventListener("change", changeHandler);
      })
   </script>
//CheckBox 就是上面的CheckBox
import CheckBox from "./CheckBox.js";

export default class Radio extends CheckBox {
   name;
   static list = new Map();
   constructor(lable, name) {
      super(lable)
      this.name = name;
      //判断list中有没有键name
      if (!Radio.list.has(name)) {
         //没有则把name设置为键,让当前的实例化对象为值
         Radio.list.set(name, this);
         //调用父类中的setChecked,并传入参数true
         this.setChecked(true);
      }
   }


   //设置 单选
   //当一个被选中时 让另外一个不被选中  
   clickHandler() {
      //如果list中有当前实例化对象(说明已经被选中了)
      if (Radio.list.has(this.name)) {
         //让其不被选中
         Radio.list.get(this.name).setChecked(false)
      }
      //如果此时该实例化对象没有被选中
      if (!this._checked) {
         //让其被选中
         this.setChecked(true);
         //并且把它加入到集合中
         Radio.list.set(this.name, this);
      }
   }

   //获取点击时背景图切换的样式
   setCheckedStyle() {
      Object.assign(this.elem.firstElementChild.style, {
         //在精灵图中 选中和未选中样式在同一行 所以不需要使用Y轴
         backgroundPositionX: this._checked ? "-175px" : "-195px"
      })
   }

   //设置初始样式
   setStyle() {
      this.elem.style.position = "relative";
      Object.assign(this.elem.firstElementChild.style, {
         width: "18px",
         height: "18px",
         backgroundImage: "url(./img/new_icon.png)",
         backgroundPositionX: "-195px",
         backgroundPositionY: "-104px",
         float: "left",
         marginRight: "5px",
         position: "relative",
         top: "1px"
      })
   }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值