JS——ES6寒假

let

  1. 块级作用域
    在for循环中的应用
    如果用var声明变量,不能在循环中想获取此刻被点击的元素,因为for循环在一瞬间就完成,最后的i值,只能是结果值(固定的)。可以通过自己设置一个属性解决。但是let不同。
    在这里插入图片描述
  2. 不可以重复声明
  3. 没有变量提升
  4. 暂时性死区
  5. 不与顶层对象(window.)挂钩。var可

const

  1. 定义常量
  2. 不可重复定义
  3. 声明不提升
  4. 块级作用域
  5. 不与顶层对象(window.)挂钩。

解构赋值

在这里插入图片描述
快速交换值

在这里插入图片描述
直接拿需要的值(空着)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
函数中
在这里插入图片描述
字符串解构
在这里插入图片描述
获取字符串的长度
在这里插入图片描述

模板字符串

原来
在这里插入图片描述
用模板字符串后
在这里插入图片描述
map
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

放表达式,函数

在这里插入图片描述

字符串扩展。

在这里插入图片描述

数值扩展

2进制8进制

2进制 0b
八进制0o

isFinite与isNaN方法

减少全局性方法,使得语言逐步模块化

let num1 = Number.isFinite(100) //true
let num2 = Number.isFinite(100/0) //false
let num3 = Number.isFinite(Infinity) // false
let num4 = Number.isFinite("100") //false
let num1 = Number.isNaN(100) // false
let num2 = Number.isNaN(NaN) //true
let num3 = Number.isNaN("fang") //false
let num4 = Number.isNaN("100") // false

它们与传统的全局方法isFinite()和isNaN()的区别在于,传统方法先调用Number()将非数值的值转为数值,再进行判断,而这两个新方法只对数值有效,Number.isFinite()对于非数值一律返回false, Number.isNaN()只有对于NaN才返回true,非NaN一律返回false。

isInteger方法

用来判断一个数值是否为整数。

let num1 = Number.isInteger(100) // true
let num2 = Number.isInteger(100.0) //true
let num3 = Number.isInteger("fang") //false
let num4 = Number.isInteger("100") // false

极小常量Number.EPSILON

它表示 1 与大于 1 的最小浮点数之间的差。2.220446049250313e-16

function isEqual(a,b){
        return Math.abs(a-b)<Number.EPSILON
}

console.log(isEqual(0.1+0.2,0.3)) //true
console.log(0.1+0.2===0.3) //false

Math.trunc

将小数部分抹掉,返回一个整数。

console.log(Math.trunc(1.2)) //1
console.log(Math.trunc(1.8))// 1
console.log(Math.trunc(-1.8)) //-1
console.log(Math.trunc(-1.2))//-1

Math.sign

Math.sign方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。

Math.sign(-100) // 
Math.sign(100) // +1
Math.sign(0) // +0
Math.sign(-0) // -0
Math.sign("fang") // NaN

数组扩展

扩展运算符

let arr1 = [1,2,3]
let arr2 = [4,5,6]

console.log([...arr1,...arr2])

Array.from

将类数组对象转换为真正数组

function test(){
        console.log(Array.from(arguments))
}

test(1,2,3)

let oli = document.querySelectorAll("li")
console.log(Array.from(oli))

Array.of

将一组值转化为数组,即新建数组

let arr1 = Array(3)
console.log(arr1)// [,,]

let arr2 = Array.of(3)
console.log(arr2)// [3]

find方法

1)该方法主要应用于查找第一个符合条件的数组元素

2)它的参数是一个回调函数。在回调函数中可以写你要查找元素的条件,当条件成立为true时,返回该元素。如果没有符合条件的元素,返回值为undefined

let arr = [11,12,13,14,15]
let res1 = arr.find(function(item){
    return item>13
})
let res2 = arr.findIndex(function(item){
    return item>13
})
console.log(res1) //14
console.log(res2) //3

fill方法

使用自己想要的参数替换原数组内容,但是会改变原来的数组

let arr1 = new Array(3).fill("fang")
let arr2 = ['a', 'b', 'c'].fill("fang", 1, 2)
console.log(arr1)//['fang', 'fang', 'fang']
console.log(arr2)// ['a', 'fang', 'c']

flat与flatMap方法

按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回

var obj = [{
                name: "A",
                list: ["鞍山", "安庆", "安阳"]
            },
            {
                name: "B",
                list: ["北京", "保定", "包头"]
            }
]
console.log(obj.flatMap(item => item.list))

对象扩展

对象简写

let name ="moduleA"
let obj = {
    name,
    test1(){

    },
    test2(){

    }
}

属性名表达式

let name ="moduleA"
let obj = {
    name,
    [name+"test1"](){

    },
    [name+"test2"](){

    }
}

Object.assign

Object.assign(target, object1,object2)的第一个参数是目标对象,后面可以跟一个或多个源对象作为参数。

target:参数合并后存放的对象

object1:参数1

object2:参数2

const obj1 = {
    name: "fang"
};

const obj2 = {
    name:"tiechui"
};
const obj3 = {
    age:100
};

Object.assign(obj1, obj2, obj3);
//obj1 {name: 'tiechui', age: 100}

Object.is

方法判断两个值是否是相同的值

console.log(NaN===NaN) //false
console.log(+0===-0) //true

console.log(Object.is(NaN,NaN)) //true
console.log(Object.is(+0,-0)) //false

函数扩展

箭头函数

  • 箭头函数是 ES6 里面一个简写函数的语法方式

  • 重点: 箭头函数只能简写函数表达式,不能简写声明式函数

    function fn() {} // 不能简写
    const fun = function () {} // 可以简写
    const obj = {
      fn: function () {} // 可以简写
    }
    
  • 语法: (函数的行参) => { 函数体内要执行的代码 }

    const fn = function (a, b) {
      console.log(a)
      console.log(b)
    }
    // 可以使用箭头函数写成
    const fun = (a, b) => {
      console.log(a)
      console.log(b)
    }
    
    const obj = {
      fn: function (a, b) {
        console.log(a)
        console.log(b)
      }
    }
    // 可以使用箭头函数写成
    const obj2 = {
      fn: (a, b) => {
        console.log(a)
        console.log(b)
      }
    }
    

箭头函数的特殊性

  • 箭头函数内部没有 this,箭头函数的 this 是上下文的 this

    // 在箭头函数定义的位置往上数,这一行是可以打印出 this 的
    // 因为这里的 this 是 window
    // 所以箭头函数内部的 this 就是 window
    const obj = {
      fn: function () {
        console.log(this)
      },
      // 这个位置是箭头函数的上一行,但是不能打印出 this
      fun: () => {
        // 箭头函数内部的 this 是书写箭头函数的上一行一个可以打印出 this 的位置
        console.log(this)
      }
    }
    
    obj.fn()
    obj.fun()
    
    • 按照我们之前的 this 指向来判断,两个都应该指向 obj
    • 但是 fun 因为是箭头函数,所以 this 不指向 obj,而是指向 fun 的外层,就是 window
  • 箭头函数内部没有 arguments 这个参数集合

    const obj = {
      fn: function () {
        console.log(arguments)
      },
      fun: () => {
        console.log(arguments)
      }
    }
    obj.fn(1, 2, 3) // 会打印一个伪数组 [1, 2, 3]
    obj.fun(1, 2, 3) // 会直接报错
    
  • 函数的行参只有一个的时候可以不写 () 其余情况必须写

    const obj = {
      fn: () => {
        console.log('没有参数,必须写小括号')
      },
      fn2: a => {
        console.log('一个行参,可以不写小括号')
      },
      fn3: (a, b) => {
        console.log('两个或两个以上参数,必须写小括号')
      }
    }
    
  • 函数体只有一行代码的时候,可以不写 {} ,并且会自动 return

    const obj = {
      fn: a => {
        return a + 10
      },
      fun: a => a + 10
    }
    
    console.log(fn(10)) // 20
    console.log(fun(10)) // 20
    

函数传递参数的时候的默认值

  • 我们在定义函数的时候,有的时候需要一个默认值出现

  • 就是当我不传递参数的时候,使用默认值,传递参数了就使用传递的参数

    function fn(a) {
      a = a || 10
      console.log(a)
    }
    fn()   // 不传递参数的时候,函数内部的 a 就是 10
    fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
    
    • 在 ES6 中我们可以直接把默认值写在函数的行参位置
    function fn(a = 10) {
      console.log(a)
    }
    fn()   // 不传递参数的时候,函数内部的 a 就是 10
    fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
    
    • 这个默认值的方式箭头函数也可以使用
    const fn = (a = 10) => {
      console.log(a)
    }
    fn()   // 不传递参数的时候,函数内部的 a 就是 10
    fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
    
    • 注意: 箭头函数如果你需要使用默认值的话,那么一个参数的时候也需要写 ()

Symbol

ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它属于 JavaScript 语言的原生数据类型之一,其他数据类型是:undefinednull、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

  1. 使用Symbol作为对象属性名
let name = Symbol()
let age = Symbol()
var obj  ={
    [name]:"fang",
    [age]:100
}
  1. Symbol()函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述。这主要是为了在控制台显示,比较容易区分。
let name = Symbol("name")
let age = Symbol("age")
var obj  ={
    [name]:"fang",
    [age]:100
}
console.log(obj)
  1. 遍历问题
let keys = {
    name:Symbol("name"),
    age:Symbol("age")
}
var obj  ={
    [keys.name]:"fang",
    [keys.age]:100,
    a:1,
    b:2,
    c:3
}

Reflect.ownKeys(obj).forEach(item=>{
    console.log(item,obj[item])
})
  1. Symbol.for()可以重新使用同一个 Symbol 值
var obj  ={
    [Symbol.for("name")]:"fang",
    [Symbol.for("age")]:100
}

console.log(obj[Symbol.for("name")])
  1. 不可以参与运算
  2. 隐式转换boolean

1.Iterator迭代器

Iterator 的作用有三个:

一是为各种数据结构,提供一个统一的、简便的访问接口;

二是使得数据结构的成员能够按某种次序排列;

三是 ES6 创造了一种新的遍历命令for…of循环,Iterator 接口主要供for…of循环

let arr = ["fang", "tiechui", "gangdaner"]

for(let i of arr){
    console.log(i)
}
Iterator 的遍历过程是这样的。

(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。

(2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。

(3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。

(4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。

let i = arr[Symbol.iterator]()
console.log(i.next())
console.log(i.next())
console.log(i.next())
console.log(i.next())

ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。

原生默认具备 Iterator 接口的数据结构如下。

  • Array
  • Set
  • Map
  • String
  • arguments 对象
  • NodeList 对象

如何对于对象进行for fo遍历?

let obj = {
    0: "fang",
    1: "tiechui",
    2: "gangdaner",
    length: 3,
    [Symbol.iterator]: Array.prototype[Symbol.iterator]
}

for (let i of obj) {
    console.log(i)
}


let obj2 = {
    data: ['fang', 'tiechui', "gangdaner"],
    [Symbol.iterator]() {
        // let _this = this
        let index = 0;
        return {
            next: () => {
                if (index < this.data.length) {

                    return {
                        value: this.data[index++],
                        done: false
                    }
                } else {
                    return {
                        value: undefined,
                        done: true
                    }
                }
            }
        }
    }
};

for (let i of obj2) {
    console.log(i)
}

Set结构

它类似于数组,但成员的值都是唯一的,没有重复的值。

初识Set

let s1 = new Set([1, 2, 3, 2, 3])
console.log(s1)

let s2 = new Set()
s2.add(1)
s2.add(2)
s2.add(3)
console.log(s2)

实例的属性和方法

  • size:返回Set实例的成员总数。

  • Set.prototype.add(value):添加某个value。

  • Set.prototype.delete(value):删除某个value,返回一个布尔值,表示删除是否成功。

  • Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员。

  • Set.prototype.clear():清除所有成员,没有返回值。

遍历

  • Set.prototype.keys():返回键名的遍历器
  • Set.prototype.values():返回键值的遍历器
  • Set.prototype.entries():返回键值对的遍历器
  • Set.prototype.forEach():遍历每个成员

复杂数据结构去重

function uni(arr) {
    let res = new Set()
    return arr.filter(item => {
        let id = JSON.stringify(item)
        if (res.has(id)) {
            return false
        } else {
            res.add(id)
            return true
        }
    })
}

var arr = [1, 2, 3, "data", {
    name: "fang"
}, {
    name: "fang"
},
           [1, 2],
           [3, 4],
           [3, 4]
          ]
console.log(uni(arr))

Map结构

类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

初识Map

let m1 = new Map()
m1.set("name","fang")
m1.set({a:1},"大连")

console.log(m1)

let m2= new Map([
    ["name","fang"],
    [{a:1},"大连"]
])
console.log(m2)

实例的属性和方法

  • size:返回 Map 结构的成员总数。

  • Map.prototype.set(key,value):添加key对应得value,返回 Map 结构本身。

  • Map.prototype.get(key):获取key对应的value

  • Map.prototype.delete(key):删除某个键(键名+键值)

  • Map.prototype.has(key):某个键是否在当前 Map 对象之中。

  • Map.prototype.clear():清除所有成员,没有返回值。

遍历

  • Map.prototype.keys():返回键名的遍历器。
  • Map.prototype.values():返回键值的遍历器。
  • Map.prototype.entries():返回所有成员的遍历器。
  • Map.prototype.forEach():遍历 Map 的所有成员。

Proxy代理

Proxy如其名, 它的作用是在对象和和对象的属性值之间设置一个代理,获取该对象的值或者设置该对象的值, 以及实例化等等多种操作, 都会被拦截住, 经过这一层我们可以统一处理,我们可以认为它就是“代理器”

.get方法

let target = {}
let proxy = new Proxy(target,{
    get(target,prop){
        return target[prop]
    }
})

.set方法

let target = {}
let proxy = new Proxy(target,{
    get(target,prop){
        return target[prop]
    },
    set(target,prop,value){
        if(prop==="data"){
            box.innerHTML = value
        }
        target[prop] = value;
    }
})

.has方法

let target = {
    _prop: "内部数据"
}
let proxy = new Proxy(target, {
    get(target, prop) {
        return target[prop]
    },
    set(target, prop, value) {
        if (prop === "data") {
            box.innerHTML = value
        }
        target[prop] = value;
    },
    has(target, key) {
        if (key[0] === '_') {
            return false;
        }
        return key in target;
    }
})

.this问题

let target = new Set()
const proxy = new Proxy(target, {
    get(target, key) {
        const value =  target[key]
        // 遇到 Function 都手动绑定一下 this
        if (value instanceof Function) {
            console.log(`访问${value}方法了`)
            return value.bind(target)
            //不能 是 call apply 
        }
        return value
    }
})
proxy.add(1)

Proxy本质上属于元编程非破坏性数据劫持,在原对象的基础上进行了功能的衍生而又不影响原对象,符合松耦合高内聚的设计理念。

Reflect对象

Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与 Proxy 是对应的。

代替Object的某些方法

const obj = {
};
Reflect.defineProperty(obj, 'name', {
    value: 'fang',
    writable: false,
    configurable:false
});


修改某些Object方法返回结果

// 老写法
try {
  Object.defineProperty(target, property, attributes);
  // success
} catch (e) {
  // fail
}

// 新写法
if (Reflect.defineProperty(target, property, attributes)) {
  // success
} else {
  // fail
}

命令式变为函数行为

const obj = {
    name:"fang"
};
//老写法
console.log("name" in obj) //true
//新写法
console.log(Reflect.has(obj, 'name')) //true

//老写法
delete obj.name
//新写法
Reflect.deleteProperty(obj, "name")

配合Proxy

let target = new Set()
const proxy = new Proxy(target, {
    get(target, key) {
        const value = Reflect.get(target,key)
        // 遇到 Function 都手动绑定一下 this
        if (value instanceof Function) {
            console.log(`访问${value}方法了`)
            return value.bind(target)
            //不能 是 call apply 
        }
        return value
    },
    set() {
        return Reflect.set(...arguments)
    }
})
proxy.add(1)
let arr = [1, 2, 3]
let proxy = new Proxy(arr, {
    get(target, key) {
        console.log('get', key)
        return Reflect.get(...arguments)
    },
    set(target, key, value) {
        console.log('set', key, value)
        return Reflect.set(...arguments)
    }
})
proxy.push(4)
// 能够打印出很多内容
// get push     (寻找 proxy.push 方法)
// get length   (获取当前的 length)
// set 3 4      (设置 proxy[3] = 4)
// set length 4 (设置 proxy.length = 4)

Promise

Promise 是异步编程的一种解决方案,比传统的解决方案回调函数, 更合理和更强大。ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象 。

  • 指定回调函数方式更灵活易懂。

  • 解决异步 回调地狱 的问题。

回调地狱

  • 当一个回调函数嵌套一个回调函数的时候

  • 就会出现一个嵌套结构

  • 当嵌套的多了就会出现回调地狱的情况

  • 比如我们发送三个 ajax 请求

    • 第一个正常发送
    • 第二个请求需要第一个请求的结果中的某一个值作为参数
    • 第三个请求需要第二个请求的结果中的某一个值作为参数
    ajax({
      url: '我是第一个请求',
      success (res) {
        // 现在发送第二个请求
        ajax({
          url: '我是第二个请求'data: { a: res.a, b: res.b },
          success (res2) {
            // 进行第三个请求
            ajax({
              url: '我是第三个请求',
              data: { a: res2.a, b: res2.b },
      				success (res3) { 
                console.log(res3) 
              }
            })
          }
        })
      }
    })
    
  • 回调地狱,其实就是回调函数嵌套过多导致的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EGn8SyMH-1674772021491)(%E7%AC%94%E8%AE%B0.assets/%E5%9B%9E%E8%B0%83%E5%9C%B0%E7%8B%B1.jpeg)]

  • 当代码成为这个结构以后,已经没有维护的可能了

Promise使用

  • 语法:

    new Promise(function (resolve, reject) {
      // resolve 表示成功的回调
      // reject 表示失败的回调
    }).then(function (res) {
      // 成功的函数
    }).catch(function (err) {
      // 失败的函数
    })
    

在这里插入图片描述

Promise 对象的状态

Promise 对象通过自身的状态,来控制异步操作。Promise 实例具有三种状态。

异步操作未完成(pending)
异步操作成功(fulfilled)
异步操作失败(rejected)

这三种的状态的变化途径只有两种。

从“未完成”到“成功”
从“未完成”到“失败”

一旦状态发生变化,就凝固了,不会再有新的状态变化。这也是 Promise 这个名字的由来,它的英语意思是“承诺”,一旦承诺成效,就不得再改变了。这也意味着,Promise 实例的状态变化只可能发生一次。

因此,Promise 的最终结果只有两种。

异步操作成功,Promise 实例传回一个值(value),状态变为fulfilled。
异步操作失败,Promise 实例抛出一个错误(error),状态变为rejected。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WstExCHL-1674772021494)(%E7%AC%94%E8%AE%B0.assets/image-20220902141409899.png)]

.all

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.all([p1, p2, p3]);

p的状态由p1,p2,p3 决定,分成两种情况。

(1)只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1p2p3之中有一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.race

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1p2p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

Generator 函数

Generator 函数是 ES6 提供的一种异步编程解决方案

Generator 函数是一个状态机,封装了多个内部状态。

执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

基本语法

function *gen(){
    console.log(1)
    yield;
    console.log(2)
    yield;
    console.log(3)
}

let g = gen()
g.next()
g.next()
g.next()

yield(产出)表达式是暂停执行的标记,而next方法可以恢复执行。

function *gen(){
    yield  1;
    yield  2;
}

let g = gen()
let res1 = g.next()
console.log(res1)
let res2 = g.next()
console.log(res2)
let res3 = g.next()
console.log(res3)
function *gen(){
    let res1 = yield;
    console.log(res1)
    let res2 = yield;
    console.log(res2)
}

let g = gen()
g.next("data-1")
g.next("data-2")
g.next("data-3")

异步流程

手动版本

function *gen(){
    let res1 = yield ajax("1.json")
    console.log(res1)
    let res2 = yield ajax("2.json")
    console.log(res2)
}

let g = gen()   

g.next().value.then(data=>{
    g.next(data).value.then(data=>{
        g.next(data)
    })
}) 

自动版本

function* gen() {
    let res1 = yield ajax("1.json")
    console.log(res1)
    let res2 = yield ajax("2.json")
    console.log(res2)
}


function AutoRun(gen) {
    let g = gen();

    function next(data) {
        let res = g.next(data);
        if (res.done) return 
        res.value.then(function (data) {
            next(data);
        });
    }

    next();
}

AutoRun(gen);

Class语法

类的写法

class Person {
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    say(){
        console.log(this.name,this.age)
    }
}
let obj = new Person("fang",100)
console.log(obj)

getter与setter

class List{
    constructor(ele){
        this.element = ele
    }

    get html(){
        return this.element.innerHTML
    }
    set html(arr){
        this.element.innerHTML = arr.map(item=>`<li>${item}</li>`).join("")
    }
}
let obj = new List(document.querySelector("##list"))

obj.html = ["aaa","bbb","cccc"]

静态属性和静态方法

class Person {
    static name = "Person这个类"
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    say(){
        console.log(this.name,this.age)
    }

    static eat(){
        console.log("eat")
    }
}
let obj = new Person("fang",100)

console.log(Person.name)
Person.eat()

继承

ES6 规定,子类必须在constructor()方法中调用super(),否则就会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。如果不调用super()方法,子类就得不到自己的this对象。

class Person {
    static name = "Person这个类"
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    say(){
        console.log(this.name,this.age)
    }

    static eat(){
        console.log("eat")
    }
}
class Student extends Person{
    constructor(name,age,score){
        super(name,age)
        this.score = score
    }
    say(){
        super.say()
        console.log(this.score)
    }

    static eat(){
        super.eat();
        console.log("student eat")
    }
}
let obj = new Student("fang",100,200)
console.log(obj)
obj.say()
Student.eat()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值