class类的使用

类的使用

严格模式
  'use strict'
  console.log(this);  //  win 这里的区域本来就是win 所以这个是win
  function aa(){
    console.log(this);   // undefind这里的作用域不再默认是win,而是undefind,这就是严格模式,,在另一个作用域中,不默认未win
  }
  aa() 
类的基本语法
class User{           // 声明类
  constructor(name){  // 构造函数,new的时候会自动执行
    this.name = name  // 此处的this,一般是new出来的对象
  }
  getName(){
    return this.name  // 此处的this,一般是new出来的对象
  }
}

let my = new User("大傻逼")
console.log(my.name);
console.log(my.getName());
类与原型
  class User {
    constructor(name){
      this.nme = name    // 在这里定义属性的作用就是可以让new出来的对象单独拥有他,和其他new出来互相不影响的,而下面定义的方法则是放原型中中的
    }
    show() { }
  }
  function aa() { }
  console.dir(User);
  console.dir(aa)
  // 其实类的本质就是函数,可以看到输出的user和aa都是一样的原型结构
  // 并且等于自己原型中的constructor
  console.log(  User === User.prototype.constructor);
  // 并且在类中定义函数是自动放到类的原型当中的,也就是User.prototype

  let user = new User('大傻逼')
  console.dir(user);
  // 结构如下图

在这里插入图片描述

  // 通过获取对象属性,结果如下图
  console.log( Object.getOwnPropertyNames(user));             // 获取new出来的对象的属性只有一个name,自己独有的
  console.log(  Object.getOwnPropertyNames(User.prototype));  // 获取原型中属性 

在这里插入图片描述

  class User {
    name2 = '小煞笔'       // 当我在这里定义属性 name2的时候,定义到的是这个类中,或者说就是这个函数当中,他是不会放到原型当中的,new出来的队形都会带有这个值
    constructor(name){
      this.name = name    // 在这里定义属性的作用就是可以让new出来的对象单独拥有他,和其他new出来互相不影响的,而下面定义的方法则是放原型中中的
    }
    show() { }
    changeName2(val){
      this.name2 = val    // 可以以this.name2 来修改name2
    }
  }
  user.changeName2('你好呀')
  console.log(user);

在这里插入图片描述

class定义的方法不会被遍历出来
  function A(){ }
  A.prototype.show(){}
  let aa = new A()
  
  for (const key in aa) {
    console.log(key);  // show 正常的new出来的函数对象是能够被遍历的,这就是函数属性的特征,可以使用Object.getOwnPropertyDescriptor来控制
  }
  // 或者在遍历的时候,使用 Object.hasOwnProperty() 查询一下有没有这个属性
 
 // 但是在class里面定义的方法是不会别遍历的,也就是不会遍历到原型里面的方法

class类里面的是默认使用严格模式的

// 比如没有指向的this正常是指向windows,但是严格模式下就是underfind
类中的严格模式,就是除了类直接定义的construct里面的作用域,或者直接定义到类的方法,里面的this都是这个类,如果在方法内还有新开的作用域,比如函数,那么这个函数的this指的就是undefind(严格模式)
类中使用静态属性
// 使用静态属性的作用就是为了声明一些公用或者用的多的属性

class Requ{
  static host = 'http://baidu.com'
  api(url){
    return Requ.host + `/${url}`
  }
}

let obj = new Requ()
console.log(obj.api('nihao')); // 这时候就会拼接上去 
直接把函数当对象去定义方法,或者使用_proto_,定义的方法就是静态方法,直接用函数去调用就好了,通过原型定义的方法就是普通方法
<script>
  class User {
  show(){                                // 这里定义的方法是定义到prototype的,是给new出来的子代用的
    console.log('prototype方法');
  }
  static show = function(){             // 这个静态方法是定义到__proto_的,也就是自己的原型中
    console.log('static方法');
  }
}
console.dir(User);   
User.show()   // static方法
let aa = new User() 
aa.show()    // prototype方法
</script>

在这里插入图片描述

// 需求:不适用new类的形式来调用来的构造函数

class No{
  constructor(name,age){
    this.name = name
    this.age = age
  }
  static create(...args){        // 定义到_proto_
    return new this(...args)
  }
}

let no = No.create('小明',18)
console.log(no);  // 成功输出这个对象

静态方法的小案例

let user = [
  {name:'小明',age:18},
  {name:'小红',age:20},
  {name:'小蓝',age:50}
]

class User{
  constructor(data){
     this.model = data
     console.log( this.model );
  }
  get name(){                    // new出来得对象才可以使用这个方法
    console.log(this.model);
    return this.model.name
  }
  static createUser(data){                      // 通过这种方法来面对对条数据要传一个类里得麻烦情况
      return data.map(item=>new User(item))
  }
  static maxAge(data){
    console.dir(this);
    return data.sort((a,b)=>{   
      return b.age - a.age     // 高到低排序
    })[0]
  }
  static totle(data){
    return data.reduce((t,c)=>{   // 总年龄
      return t+c.age
    },0)
  }
}
// let my = User.createUser(user)
// let aaa = new User({name:'小明',age:18})
// console.log(aaa.name);
// let myage = User.maxAge(user)
// console.log();
// console.log(User.maxAge(user).name);
console.log(User.totle(user));


类中访问器的作用
class User {
  constructor(url) {
    this.url = url          // 这里也会出发set url 访问器
  }
  set url(url) {
    if (!/^https?:\/\//i.test(url)) {
      throw new Error('傻逼')
    }
    this._url = url
  }
}
let aa = new User('https://大傻逼')
// aa.url = 'https://傻逼是你'     // 起到保护的作用
console.log(aa);

使用symbol定义protected(私有)属性

    // 定义symbol属性  
    let pro = Symbol()
    class Fa{
      constructor(){
      
      }

      set host(url){  
        if (!/^a?:/i.test(url)) {
          throw new Error('傻逼')
        }
        this[pro] = {}
        this[pro].host = url
      }
    }
    class AA extends Fa{
      constructor(){
        super()
      }
    }
    let aa = new AA()
    aa.host = 'a:大傻逼'  // 通过host可以设置symbol的值,但是通过 aa[pro] 是拿不到的,因为 每次定义的 symbol都是不一样的
    console.log(aa);

类的继承

其实也就是运用了原型链的继承,如果定义了静态方法,子类也是可以直接调用的

  <script>
    class AA {
      constructor(name) {
        this.name = name
      }
      show(){
        console.log('到这');
      }

    }

    class aa extends AA {
      constructor(name) {
        super(name)
      }
      show(){
        super.show()     // 调用父级的show  
        console.log('我是儿子');
      }
    }
    console.dir(aa);
    console.dir(AA);
    let a = new aa('大撒谎比0')
    a.show()
    console.log(a);

  </script>

看下图可以看到类的继承其实就是子类的父类_proto_变成了变成了父类的原型
在这里插入图片描述
看代码可以看到可以使用super调用 父类的方法
原理:

let aa =  {
  name:'aa',
  show(){
    console.log(this.name);
  }
}

let bb = {
  name:'bb',
  __proto__:aa,
  show(){
    this.__proto__.show.call(this)    // 调用父级的show方法,并且指向现在的this 这里输出的就是bb
    console.log(this.name);
  }
}

bb.show()

使用super的作用

  <script>
    // 由于像上面代码那里,加入再多一层父级,就会发现会循坏在后面两个子级间循环,因为把this传递过去了,里面的this都是最下级的this
    // 这时候关键字super就出现了,这个关键字的作用就是在保持能够调用父级方法的同时,并且不会影响到拿到的是本身的属性,而不是父级的属性
    let common = {
      show() {
        console.log('common.show'+this.name);  // common.showbb
      }
    }
    let aa = {
      __proto__: common,
      name: 'aa',
      show() {
        super.show()   // 调用父级的show方法,并且指向现在的this 这里输出的就是bb
        console.log(this.name);
      }
    }

    let bb = {
      name: 'bb',
      __proto__: aa,
      show() {
        super.show()   // 调用父级的show方法,并且指向现在的this 这里输出的就是bb
        console.log(this.name);
      }
    }
    console.log(bb);
    bb.show()
  </script>
为什么一定要继承的类中使用super
    // 正常使用函数继承
    function aa(name){
      this.name = name
    }
    function bb(...args){
      aa.call(this,...args)
    }
    bb.prototype = Object.create(aa.prototype)
    let b = new bb('大傻逼')

    // 使用类
    class User{
      constructor(name){
        this.name = name
      }
    }

    class Admin extends User{  
        // 使用继承,这时候就会默认设置
        // constructor(...args){
        //   super(...args)
        // }

        // 使用super就相当于上面的 aa.call(this,...args)
        // 所以如果想要自定义constructor 就必须使用super
        // 并且在构造函数中必须在super后面使用this,否者会报错
    } 

super。父类方法 可以直接调用父类的方法

静态方法和原型对比
    // 再构造函数中,其实函数也是对象,再原型链中
    function User(){}
    User.myname = '大撒谎比'
    User.show = function(){
      console.log('你说撒谎比');
    }
    function Admin(){}
    Admin.__proto__ = User
    console.dir(Admin);

    // 再类中,其实再类中也是一样的道理,原理都是再原型链中
    class User1{
      static mynaem1 = '大傻逼'
      static show(){
        console.log('你呀你大傻逼');
      }
    }
    class Admin1 extends User1{}
    console.dir(Admin1);   // 得到的东西一样
函数中中实现installceof原理
  <script>
    //  a instanceof b   是检查a当前对象是否在b的原型链上
    function User(){}
    function Admin(){}

    Admin.prototype = Object.create(User.prototype)
    let ad = new Admin()
    function checkinstanceof(obj,construtor){
      if (!obj.__proto__)  return false
      if (obj.__proto__ === construtor.prototype ) return true
      return  checkinstanceof(obj.__proto__,construtor)
    }
    
    console.log(checkinstanceof(ad,User));
还可以使用isPrototypeOf 来检查继承
简易模块管理
    let module = (function () {              // 这里就是模块管理区域
      let modulesList = {}                   // 用来保存模块
      let moduleActions = []                 // 用来保存模块被引用了的时候的动作

      function define(name, modules, action) {     // 定义模块的方法
        modules.map((item,i)=>{                    // 遍历引用的模块的名字
          if (modulesList[item]) {                 // 如果这个模块存在就存起来
            moduleActions[i] = modulesList[item]
          }
        })
        modulesList[name] = action.apply(null, moduleActions)    // 执行这个动作并且存到modulesList对应模块name里面
      }
      return { define }
    })()
    module.define('aa', [], function () {    //  这里是一个用来被引用的模块 参数:名字,引用模块的名字数组,动作
      return {
        max(arr) {
          return arr.sort((a, b) => b - a)[0]
        }
      }
    })

    module.define('bb',['aa','qq'],function(res){     // 去引用模块
      console.log( res.max([1,3,9,8]));
    })
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值