02-原型继承 call借调 ES6部分用法

60 阅读1分钟

02-JS高级

1.原型-继承

 <script>
      // 爸爸 person  name属性、age属性、height、属性
      function Person(name, age, height) {
        this.username = name;
        this.age = age;
        this.height = height;
      }

      // 学生  student name属性、age属性、height属性、color颜色
      function Student(name, age, height, color) {
        this.name = name;
        this.age = age;
        this.height = height;
        this.color = color;
      }

      const p1 = new Person('奥特之父', 5000, 200);
      const s1 = new Student('迪迦', 2000, 100);

      // 我想 让 两个实例 形成父子关系     没有做到继承 
      // 父亲有的东西 儿子可以直接使用  
      // 父亲做了修改,儿子跟着发生修改


      // 稍后我们的代码如果可以做到
      // 1 父亲有的属性,儿子不用再写一次
      // 2 父亲某些属性做了修改,儿子可以跟着发生修改 
      console.log(p1);
      console.log(s1);
    </script>
  • call 借调 可以让一个对象 来借用另外一个对象的方法
  • 父亲方法.call(this,形参1,形参2)
    <script>
      function Person(name, age, height) {
        this.username = name;
        this.age = age;
        this.height = height;
      }

      function Student(name, age, height, color) {
        // 这一行代码解决了继承的问题!!
        // call 借用别人的方法
        // 谁有方法
        // 谁想要借用person方法  this = 实例 = 下面代码的s1
        Person.call(this, name, age, height);//   儿子想要复用父亲的某些代码 父亲方法.call(this,形参1,形参2。)
        // this.name = name;
        // this.age = age;
        // this.height = height;
        this.color = color;
      }

      // const p1 = new Person('奥特之父', 5000, 200);
      const s1 = new Student('迪迦', 2000, 100, 'yellow');

      // console.log(p1);
      console.log(s1);
    </script>

2.call 借用方法讲解

  <script>
      // call 借调 可以让一个对象 来借用另外一个对象的方法
      const obj = {
        name: '老王',
        skill() {
          // this = obj   this.name =  obj.name
          console.log(this.name + ' 翻墙'); // this 等于 调用者
        },
      };

      const obj2 = {
        name: '大郎',
      };

      // 大郎没有翻墙的方法 但是 老王有
      // 让大郎 借用一下 老王的翻墙功能
      // obj.skill.call(obj2); // 你有把老王的翻墙技能 借给谁使用

      const obj3={
        name:"刘同学"
      }
      obj.skill.call(obj3);//  ? 老王还是刘同学 
    </script>

3.call 借用案例解析

被借用者.call(借用者) => 超人.call(普通人)

 <script>
      const obj={
        name:"超人",
        skill(){
          console.log(this.name +" 会飞");
        }
      }
      // 超人有技能 会飞 
      const obj2={
        name:"普通人"
      };

      // 让普通人  借 一下超人的技能 skill  固定的规则 
      obj.skill.call(obj2);

    </script>

4.call 使用解析

 <script>
      // const obj = {
      //   name: '超人',
      //   skill:function(fly) {
      //     console.log(this.name + fly);
      //   },
      // };
      // obj.skill(' 会飞');
      // obj.skill(' 发射激光');
      // console.log(obj);

      // console.log(obj);{name:"超人",skill:function(){}}

      // 车
      // const car = {
      //   name: '装甲车',
      //   add:function(n1,n2,n3,n4) {
      //     // 给装甲车 武装武器  给car添加属性
      //     // n1 n2 n3 n4 武器
      //     // console.log(n1,n2,n3,n4);
      //     // console.log(this);// this = ??? 数据类型  对象类型 cart

      //     // car[n1]=n1; // n1 = A   car["A"]="A";
      //     // car[n2]=n2; // n2 = B   car["B"]="B";
      //     // car[n3]=n3;
      //     // car[n4]=n4;

      //     //  this =  car
      //     this[n1]=n1;
      //     this[n2]=n2;
      //     this[n3]=n3;
      //     this[n4]=n4;

      //   },
      // };
      // car.add("A","B","C","D");
      // console.log(car);

      // const obj={};

      // obj["username"]="普通人";// 是什么意思 ? 给obj对象添加属性
      // console.log(obj);

      const car = {
        name: '装甲车',
        add: function (username, age) {
          // 本质 可以给car添加新的属性
          this.username = username;
          this.age = age;
        },
      };

      // car.add('发动机', 100);
      // console.log(car);

      const obj = {};
      // car.add.call(obj); // obj 想要借用 添加属性的方法
      car.add.call(obj, '发动机', 200); // call 传入参数  add.call(谁要借用,被借用的方法的形参1,被借用的方法形参2)
      console.log(obj); // obj 有没有 username属性(不用管属性值)、有没有age属性(不用属性值)


      // 可以实现 了 一个空对象 obj 通过call的使用 来实现了 借别人的方法add 来给obj添加新的属性 
    </script>

5.属性-方法继承

儿子的原型.say = 父亲的原型.say

<script>
      // 对象 两个大的特点
      // 属性 - 属性的继承
      // 行为-方法
      // 让儿子也具有父亲的行为  =>  把父亲的DNA 给到儿子即可
      // 给儿子添加行为 儿子的原型上添加
      // 父亲的行为 存放在父亲原型上

      function Person(name, age) {
        this.username = name;
        this.age = age;
      }

      Person.prototype.say = function () {
        console.log(this.username, this.age); // 我是谁 我的年龄是
      };
      Person.prototype.show = function () {
        console.log(this.username + ' 秀肌肉');
      };

      // const p1=new Person("父亲",50);
      // p1.say();

      function Student(name, age, color) {
        // name age person里面已经有定义
        // 借用一下
        Person.call(this, name, age);

        // color person里面没有的 需要自己来定义
        this.color = color;
      }
      const s1 = new Student('三好学生', 10, 'yellow');

      // 把父亲的行为 也设置到儿子上
      Student.prototype.say = Person.prototype.say;
      Student.prototype.show = Person.prototype.show;

      s1.say();
      s1.show();

      /* 
      总结
      想要实现继承的功能 分两个部分
      1 属性的继承
        Person.call(this,其他参数)
      2 方法的继承
        儿子的原型.say =  父亲的原型.say 
      
       */
    </script>

6.继承的案例

  <script>
      /* 
      封装 代码 实现以下的功能
      1 父亲   Element
        1 属性 dom   this.dom
        2 行为 实例.append(父元素标签的选择器)
      2 儿子1  ElementDouble  div
        1 继承父亲 Element  
          属性 dom
          行为 append
      3 儿子2  ElementSingle  img 
          属性 dom
          行为 append

      4 当执行以下代码时 出现对应效果
        1 const divModel = new ElementDouble("div","div内的文字")
        2 divModel.append("body") ;  body标签可以出现 一个 div 

        1 const imgModel = new ElementSingle("img","图片地址")
        2 imgModel.append("body");  body标签可以出现 一个图片 
       */

      //  父亲
      function Element() {
        this.dom = null;
      }
      //  父亲
      Element.prototype.append = function () {};

      // 儿子1
      function ElementDouble(tagName, content) {
        const dom = document.createElement(tagName);
        dom.innerText = content;
        this.dom = dom;
      }
      ElementDouble.prototype.append = function (parentSelector) {
        // 真正的dom父元素.appendChild(子元素)
        document.querySelector(parentSelector).appendChild(this.dom);
      };

      // 儿子2
      function ElementSingle(tagName, src) {
        const dom = document.createElement(tagName); // 图片
        dom.src = src;
        this.dom = dom;
      }
      ElementSingle.prototype.append = function (parentSelector) {
        document.querySelector(parentSelector).appendChild(this.dom);
      };

      const divModel = new ElementDouble('div', 'div内的文字');
      divModel.append('body');

      const imgModel = new ElementSingle('img', './images/b_01.jpg');
      imgModel.append('body');

      // 如果代码重复实现了 很有可能就是我们要封装的时候
      // 以前的封装 仅仅是封装一个小小的函数而已
      // 现在的封装, 面相对象的思维来封装
      // 封装 属性  父亲
      // 封装 方法  父亲
    </script>

封装之后的代码

  <script>
      /* 
      封装 代码 实现以下的功能
      1 父亲   Element
        1 属性 dom   this.dom
        2 行为 实例.append(父元素标签的选择器)
      2 儿子1  ElementDouble  div
        1 继承父亲 Element  
          属性 dom
          行为 append
      3 儿子2  ElementSingle  img 
          属性 dom
          行为 append

      4 当执行以下代码时 出现对应效果
        1 const divModel = new ElementDouble("div","div内的文字")
        2 divModel.append("body") ;  body标签可以出现 一个 div 

        1 const imgModel = new ElementSingle("img","图片地址")
        2 imgModel.append("body");  body标签可以出现 一个图片 
       */

      //  父亲
      function Element(tagName) {
        const dom = document.createElement(tagName);
        this.dom = dom;
      }
      //  父亲
      Element.prototype.append = function (parentSelector) {
        document.querySelector(parentSelector).appendChild(this.dom);
      };

      // 儿子1
      function ElementDouble(tagName, content) {
        Element.call(this, tagName); // 继承 - 父亲的属性
        this.dom.innerText = content;
      }
      // 去继承父亲的行为
      ElementDouble.prototype.append = Element.prototype.append;

      // 儿子2
      function ElementSingle(tagName, src) {
        Element.call(this, tagName);
        this.dom.src = src;
      }
      ElementSingle.prototype.append = Element.prototype.append;

      const divModel = new ElementDouble('div', '这个是div');
      divModel.append('body');

      const imgModel = new ElementSingle('img', './images/b_01.jpg');
      imgModel.append('div');

      // 如果代码重复实现了 很有可能就是我们要封装的时候
      // 以前的封装 仅仅是封装一个小小的函数而已
      // 现在的封装, 面相对象的思维来封装
      // 封装 属性  父亲
      // 封装 方法  父亲

      // 两个儿子的代码 有重复部分
      // 创建标签重复 this.dom=dom  append方法也重复

      // 儿子1 有要什么功能
      // 先复用父亲的属性和方法

      // 分享
      // 在公司中,
      // 会调用代码的人 工作技术难度低(劳动量大),工资有上限
      // 还是会封装代码的人 工作技术难度高(劳动量不大) 工资高

      // 你感觉很难的知识,大佬都特别喜欢 是他们再次提高技术天花板的时候-提高收入-提高薪资

      // 金子塔上总是少部分的
      // 绝大部分的人过过多考虑自己的学习感受 而花很少时间去思考如何提高
      // 大佬 自己 死尸没有什么感受,  技术有用,能提高技术-如何去学
    </script>

ES6

1.函数参数默认值

 <script>
      // 目前浏览器 支持的js的代码版本
      // 主要都支持 es5 (for if while 函数 forEach ) 版本
      // 新的语法 es6 (提供了更加简单强大的代码更能力) 提高我们的开发效率
      // 常用 重要的部分
      // 如果大家有空 了解全部 阮一峰

      // 体验一下
      // 交换
      let a = 1;
      let b = 2;
      // 交换两个值
      [a,b]=[b,a];
      console.log(a,b);

      // let c = a;
      // a = b;
      // b = c;
      // console.log(a, b);
    </script>

2.对象属性方法简写

如果变量的名字和属性的名字 一致的话,对象可以简写

属性简写

/ const obj = {
      //   // 属性名 和 属性值
      //   username: 123,
      // };

      const username = 123;
      const color = 'red';

      const say = function () {};

      function show() {}

      // 很常用
      const obj = {
        username, // username:username
        color, // color : color
        say,
        show,
        height: 100,
      };

      obj.height = 200;
      // console.log(obj);

方法简写

方法名(){}

 // 对象中方法的简写
      const person={
        show:function(){
          console.log("show");
        },// 常规写法
        // es6 关于 方法简写
        say(){
          console.log("say");
        } // es6 关于 方法简写
      }
      person.show();
      person.say();

3.解构(数组 对象)

  <script>
      // dataset = { index:100}
      // const dataset= document.querySelector('div').dataset;
      // const { index,num } = document.querySelector('div').dataset;
      // console.log(dataset);
      // const {index}=dataset;
      // console.log(index);
      // console.log(num);
      // const arr = ['悟空', '八戒', '龙马', '三藏'];
      // 希望 声明四个变量  a = 悟空  b = 八戒 。。。
      // 下次我看到谁这么写代码的, 手都打肿!!!
      // 太low!! 低级  我自己 无地自容  想不开你
      // const a = arr[0];
      // const b = arr[1];
      // const c = arr[2];
      // const d = arr[3];

      // 数组解构
      // const  [a,b,c,d]=arr;
      // const [a, b, c, d] = ['悟空', '八戒', '龙马', '三藏',"沙僧"];
      // console.log(a, b, c, d);

      // 对象的解构
      // const obj = {
      //   username: '悟空',
      //   height: 100,
      // };

      // 声明两个变量 来获取obj的两个属性
      // low 代码!!!
      // const username = obj.username;
      // const height = obj.height;

      // 对象解构
      // const { username, height } = obj;
      // console.log(username, height);

      // 解构 + 默认值
      // const arr = [1,100];
      // const [a,b ] = arr; a = 1 b=undefined
      // const [a, b = 2] = arr;
      // console.log(a, b); // a =1  b = 2

      // b = 2 默认值 (你没有,就使用我,你有,使用你的)
      // const [a, b = 2] = arr;
      // console.log(a,b);

      const obj = {
        username: 100,
        height: 500,
      };
      const { username, height = 200 } = obj;
      console.log(username, height);

      /* 
      小结
      1 解构 对象 和 数组上
        对象 
        const  { username,height } = {username:"悟空",height:200}
        数组
        const [a,b]=[100,200];

     2 解构 + 默认值
       如果 右边的对象中没有height 属性 那么 height变量 =  1000 
       const  { username,height=1000 } = {username:"悟空",height:200} 
        
      //  c 在右边找不到对应的数据 c 就使用默认值 300 
        const [a,b,c=300]=[100,200];
       */
    </script>

4.拓展运算符

  • ... 拓展运算符
  • 获取剩下的 展开
 <body>
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
    </ul>
    <script>
      // ...
      // 拓展运算符 以下三点
      // ...   获取剩下 展开

      // 获取剩下 数组
      // const [a,b,...c]=[1,2,3,4,5,6,7];
      // const [a,b,...c]=[1,2,3];
      // const [a, b, ...c] = [1, 2];
      // console.log(a,b); // 1 , 2
      // console.log(c);// [3,4,5,6,7]
      // console.log(c); //  [3]
      // console.log(c); //  []

      // 获取剩下 对象
      // const { a, ...c } = { a: 1, b: 2, c: 3 };
      // const { a,b,c ,...d } = { a: 1, b: 2, c: 3 };
      // console.log(c);// ? {b:2,c:3}
      // console.log(d); // ?

      // const [...a]=[1,2,3,4];
      // console.log(a);// [1,2,3,4]
      // console.log(a.map);
      // const lis = document.querySelectorAll('li');// lis 伪数组 没有map方法
      // const newList = [...lis]; // 如何理解 ? 转成真正的数组
      // console.log(newList.map);

      // 获取剩下 用在函数的形参上

      // 计算数据和的功能
      // calc(1,2)// 1 + 2
      // calc(1,2,3) // 1 + 2 + 3
      // calc(1,2,3,4) // 1 + 2 + 3 + 4
      function calc(...args) {
        // args 数组 装载这所有传给calc的参数
        // console.log(args);
        let sum = 0;
        args.forEach((value) => (sum += value));
        console.log(sum);
      }
      calc(1, 2); // ? [1,2]
      calc(1, 2, 3); // [1,2,3]
      calc(1, 2, 3, 4); // [1,2,3,4]


      /* 
      剩余运算符
      1 数组中  const [a,b,...c]=[1,2,3,4,5,6,7];  c =[3,4,5,6,7]
        应用场景 伪数组转真正的数组
      2 对象中  const { a,...d } = { a: 1, b: 2, c: 3 }; // d = {b:2,c:3 }
      3 函数的形参中  
        calc(1, 2, 3);   function calc(...args) {}  // args = [1,2,3]
       计算数字总和 

      4 练习题目 
        getMax(1,2,3) // 输出3 
        getMax(1,4) // 输出4
        getMax(1,20,4) // 输出20 
        getMax(1,20,4,30,2) // 输出30
      
       */
    </script>
  </body>

5.计算最大值

<script>
      // 计算最大值的写法 
      function getMax(...args) {
        // args= 数组  接收 所有传递给 getMax方法的 参数
        // console.log(args);
        // 计算最大值 的
        let max = args[0];
        args.forEach((value) => {
          if (value > max) {
            max = value;
          }
        });
        console.log(max);
      }

      // getMax(1);
      // getMax(1, 2);
      // getMax(1, 2, 3);
      // getMax(11, 33, 2, 3);

      // Math对象 自己就封装过 计算最大值和最小值的代码
      // console.log(Math.max(1,3,4,2));// 4
      // console.log(Math.min(1,3,4,2));// 1

      function getMax2(...args) {
        // Math.max(1,3,4,2)
        // args=[1,3,4,3]
        // Math.max([1,3,4,3]) =>  Math.max(1,3,4,2)
        // 剩余运算符的

        console.log(  Math.max(...args));
      }
      // getMax2(1,2,3);
      // getMax2(1,2,33);
      // console.log(Math.max(...[1,3,4,3])); //  Math.max(1,3,4,2)

      getMax2(1,2,3,4); // 体现的思想 不再是 剩余 。  展开-延展-拓展 思想 
    </script>

6.展开 ... 的用法

 <script>
      // 展开 ... 用法
      // const obj = {
      //   username: '悟空',
      //   height: 200,
      // };

      // // 新创建一个对象 这个对象 具有 所有 obj的属性
      // // 同时 还有多一个属性,color

      // // const newObj = obj;// 对象是引用类型   写 =  将 obj的地址 给了一份 newObj  两个变量指向的地址同样的 同一个对象
      // // newObj.color = 'yellow';
      // // console.log("新的对象",newObj);
      // // console.log("旧的对象",obj);

      // // 建议这做  互补影响
      // const newObj = { ...obj, color: 'yellow' }; // 给newObj 开辟新的内存空间
      // // const newObj={ username:"悟空",height:20}; // 给newObj 开辟新的内存空间
      // newObj.username = '八戒';
      // newObj.weight = 100;
      // console.log(obj);
      // console.log(newObj);

      // 展开运算符 对数组操作
      const arr = ['a', 'b', 'c'];
      // 在数组的后面 新增一个 元素 'd'
      // const newArr=[...arr,'d'];

      // 在数组宅前面 新增一个属性 w
      // console.log(newArr);
      // const newArr = ['w', ...arr];
      // console.log(newArr);
      // arr.push 
      // arr.unshift
      // 中间 无法使用 ...
      // splice 来实现 
    </script>