Skip to content

Js11

代理
//  ES5
// let obj = {}
// let newVal = ''
// Object.defineProperty(obj, 'name', {
//     get(){
//         return newVal
//     },
//     set(val){
//         console.log('set')
//         // this.name = val
//         newVal = val
//     }
// })
// obj.name = 'es'
// console.log(obj.name)

// proxy
// let obj = {}
// let p = new Proxy(obj, {})
// obj.name = 'imooc'
// console.log(obj.name)
// for(let key in obj){
//     console.log(key)
// }

// get
// let arr = [7, 8, 9]
// arr = new Proxy(arr, {
//     get(target, prop) {
//         // console.log(target, prop)
//         return prop in target ? target[prop] : 'error'
//     }
// })
// console.log(arr[1])
// console.log(arr[10])

// let dict = {
//     'hello': '你好',
//     'world': '世界'
// }
// dict = new Proxy(dict, {
//     get(target, prop) {
//         return prop in target ? target[prop] : prop
//     }
// })
// console.log(dict['world'])
// console.log(dict['imooc'])

// set
// let arr = []
// arr = new Proxy(arr, {
//     set(target, prop, val) {
//         if (typeof val === 'number') {
//             target[prop] = val
//             return true
//         } else {
//             return false
//         }
//     }
// })
// arr.push(5)
// arr.push(6)
// console.log(arr[0], arr[1], arr.length)

// has
// let range = {
//     start: 1,
//     end: 5
// }

// range = new Proxy(range, {
//     has(target, prop){
//         return prop >= target.start && prop <= target.end
//     }
// })
// console.log(2 in range)
// console.log(9 in range)

// ownKeys
// let obj = {
//     name: 'imooc',
//     [Symbol('es')]: 'es6'
// }
// console.log(Object.getOwnPropertyNames(obj))
// console.log(Object.getOwnPropertySymbols(obj))
// console.log(Object.keys(obj))
// for(let key in obj){
//     console.log(key)
// }

// let userinfo = {
//     username: 'xiecheng',
//     age: 34,
//     _password: '***'
// }
// userinfo = new Proxy(userinfo, {
//     ownKeys(target) {
//         return Object.keys(target).filter(key => !key.startsWith('_'))
//     }
// })

// // for (let key in userinfo) {
// //     console.log(key)
// // }
// console.log(Object.keys(userinfo))

// let user = {
//     name: 'xiecheng',
//     age: 34,
//     _password: '***'
// }
// user = new Proxy(user, {
//     get(target, prop) {
//         if (prop.startsWith('_')) {
//             throw new Error('不可访问')
//         } else {
//             return target[prop]
//         }
//     },
//     set(target, prop, val) {
//         if (prop.startsWith('_')) {
//             throw new Error('不可访问')
//         } else {
//             target[prop] = val
//             return true
//         }
//     },
//     deleteProperty(target, prop) { // 拦截删除
//         if (prop.startsWith('_')) {
//             throw new Error('不可删除')
//         } else {
//             delete target[prop]
//             return true
//         }
//     },
//     ownKeys(target) {
//         return Object.keys(target).filter(key => !key.startsWith('_'))
//     }
// })
// console.log(user.age)
// console.log(user._password)
// user.age = 18
// // console.log(user.age)
// // try {
// //     user._password = 'xxx'
// // } catch(e){
// //     console.log(e.message)
// // }

// // try {
// //     // delete user.age
// //     delete user._password
// // } catch (e) {
// //     console.log(e.message)
// // }
// // console.log(user.age)

// for(let key in user){
//     console.log(key)
// }

// apply
// let sum = (...args) => {
//     let num = 0
//     args.forEach(item => {
//         num += item
//     })
//     return num
// }

// sum = new Proxy(sum, {
//     apply(target, ctx, args) {
//         return target(...args) * 2
//     }
// })
// console.log(sum(1, 2))
// console.log(sum.call(null, 1, 2, 3))
// console.log(sum.apply(null, [1, 2, 3]))

// construct  new
let User = class {
    constructor(name) {
        this.name = name
    }
}
User = new Proxy(User, {
    construct(target, args, newTarget) {
        console.log('construct')
        return new target(...args)
    }
})
console.log(new User('imooc'))
对象
// let name = 'xiecheng'
// let age = 34
// let s = 'school'
// let obj = {
//     name,
//     age,
//     [s]: 'imooc',
//     study(){
//         console.log(this.name + '正在学习')
//     }
// }
// // console.log(obj)
// obj.study()

// console.log(Object.is(2, '2'))
// console.log(Object.is(NaN, NaN))
// console.log(Object.is(+0, -0))
// let obj1 = {  // new Object()
//     name: 'xiecheng',
//     age: 34
// }

// let obj2 = { // new Object()
//     name: 'xiecheng',
//     age: 34
// }
// console.log(obj1 == obj2) // false

// console.log(Object.is(obj1, obj2)) // false
// let obj2 = obj1
// console.log(Object.is(obj1, obj2)) // true

// let x = {
//     a: 3,
//     b: 4
// }
// // let y = {...x}
// let y = {
//     c: 5,
//     a: 6
// }
// // Object.assign(y, x)
// // console.log(y)
// console.log('aa' in x)

// let arr = [1, 2, 3]
// console.log(2 in arr)
let obj = {
    name: 'xiecheng',
    age: 34,
    school: 'imooc'
}
// for(let key in obj){
//     console.log(key, obj[key])
// }

// Object.keys(obj).forEach(key => {
//     console.log(key, obj[key])
// })

// Object.getOwnPropertyNames(obj).forEach(key => {
//     console.log(key, obj[key])
// })

Reflect.ownKeys(obj).forEach(key => {
    console.log(key, obj[key])
})
对象结构
// function foo(x, y){
//     y = y || 'world'
//     console.log(x, y)
// }
// // foo('hello', 'imooc')
// foo('hello', 0)

// function foo(x, y = 'world'){
//     console.log(x, y)
// }
// foo('hello', 0)

// function foo(x = 5) {
//     // let x = 1
//     const x = 1
// }
// foo()

// function foo(x, x, y = 5) {
//     // let x = 1
//     // const x = 1
// }
// foo()

// function foo(x, z, y = 5) {
//     console.log(x, y, z)
// }
// foo(1, 2)

// function foo({x, y = 5}){
//     console.log(x, y)
// }

// foo({})
// foo({
//     x: 1,
//     y: 2
// })
// foo()

// function ajax(url, {
//     body = '',
//     method = 'GET',
//     headers = {}
// } = {}){
//     console.log(method)
// }

// ajax('http://www.imooc.com', {
//    method: 'POST'
// })

// function foo(x = 1, y = 2, z = 3){
//     console.log(x, y)
// }
// console.log(foo.length)

// let x = 1
// function foo(x, y = x){
//     console.log(y) // 2
// }
// foo(2)

// let x = 1

// function foo(y = x) {
//     let x = 2
//     console.log(y) // 1
// }
// foo()

// function foo(y = x){
//     let x = 2
//     console.log(y)
// }
// foo()

// function foo(){}
// console.log(foo.name)

// console.log((new Function).name) //anonymous

function foo(x, y){
    console.log(this, x, y)
}

// foo.bind({name: 'xiecheng'})(1, 2)
// console.log(foo.bind({}).name)

console.log((function(){}).bind({}).name)
继承
// 类
function People(name, age) {
    // console.log(this)
    // 实例属性
    this.name = name
    this.age = age
    People.count++
}
// 静态属性
People.count = 0
// 静态方法
People.getCount = function(){
    console.log(this.age) // undefined
    console.log('当前共有' + P eople.count + '个人')
}

// 实例方法
People.prototype.showName = function () {
    console.log('我的名字是' + this.name)
}
let p1 = new People('xiecheng', 34)
console.log(p1)
p1.showName()

let p2 = new People('zhangsan', 20)
console.log(p2)
p2.showName()

console.log(People.count)
People.getCount()

// let str = new String('imooc')
// console.log(str)

// let arr = new Array(1, 2, 3)
// console.log(arr)

// let obj = new Object()
// obj.name = 'xiecheng'
// console.log(obj)

// 静态方法
// console.log(Math.max(4, 5))
// console.log(Math.random())

// 父类
function Animal(name) {
    this.name = name
}
Animal.prototype.showName = function () {
    console.log('名字是:' + this.name)
}

// 子类
function Dog(name, color) {
    Animal.call(this, name) // 继承属性
    this.color = color
}
Dog.prototype = new Animal()
Dog.prototype.constuctor = Dog

let d1 = new Dog('wangcai', 'white')
console.log(d1)
d1.showName()


class People {
    constructor(name, age) {
        this.name = name
        this.age = age
        this._sex = -1
    }
    // static count = 0
    get sex() { // 属性
        if (this._sex === 1) {
            return 'male'
        } else if (this._sex === 0) {
            return 'female'
        } else {
            return 'error'
        }
    }
    set sex(val) { // 1:male 0:female
        if (val === 0 || val === 1) {
            this._sex = val
        }
    }
    showName() {
        console.log(this.name)
    }
    // 静态方法
    static getCount() {
        return 5
    }
}
// 静态属性
People.count = 9
console.log(typeof People) // function
console.log(People.count)

let p1 = new People('xiecheng', 34)
console.log(p1)
p1.sex = 5
console.log(p1.sex)
console.log(People.getCount())

class Coder extends People {
    constructor(name, age, company) {
        super(name, age)
        this.company = company
    }
    showCompany() {
        console.log(this.company)
    }
}

let c1 = new Coder('zhangsan', 25, 'imooc')
console.log(c1)
c1.showName()
c1.showCompany()
c1.sex = 1
console.log(c1.sex)
console.log(Coder.getCount())

箭头函数
// console.log(sum(4, 5))

// function sum(x, y) {
//     return x + y
// }

// console.log(sum)
// let sum = function(x, y){
//     return x + y
// }

// let sum = (x, y) => {
//     return x + y
// }
// let sum = (x, y) => x + y
// console.log(sum(3, 4))

// let x = x => x

// let x = function(x){
//     return x
// }

// let oBtn = document.querySelector('#btn')
// oBtn.addEventListener('click', function () {
//     // console.log(this)
//     // setTimeout(function () {
//     //     // call apply bind
//     //     console.log(this)
//     // }.bind(this), 1000)
//     setTimeout(() => {
//         console.log(this)
//     }, 1000)
// })

// 类
// function People(name, age){
//     console.log(this)
//     this.name = name
//     this.age = age
// }
// let People = (name, age) => {
//     this.name = name
//     this.age = age
// }
// let p1 = new People('xiecheng', 34)
// console.log(p1)

let foo = (...args) => {
    // console.log(arguments)
    console.log(args)
}
foo(1, 2, 3)
解构赋值
// let arr = [1, 2, 3]
// let a = arr[0]
// let b = arr[1]
// let c = arr[2]
// let [a, b, c] = [1, 2, 3]
// console.log(a, b, c)

// let [a, b, [c, d]] = [1, 2, [3, 4]]
// console.log(a, b, c, d)

// let [a, b, [c]] = [1, 2, [3, 4]]
// console.log(a, b, c)

// let [a, b, c] = [1, 2, [3, 4]]
// console.log(a, b, c)

// let [a, b, c, d = 5] = [1, 2, [3, 4], 6]
// console.log(a, b, c, d)

// let user = {
//     name: 'xiecheng',
//     age: 34
// }
// // let name = user.name
// // let age = user.age
// let {age: uage, name: uname} = user

// console.log(uname, uage)

// let str = 'imooc'
// // for (let i = 0; i < str.length; i++) {
// //     console.log(str[i])
// // }
// let [a, b, c, d, e] = str
// console.log(a, b, c, d, e)

// let [a, b, c = 8] = [4, 5, 6]
// console.log(a, b, c)

// let {name, age = 18} = {
//     name: 'xiecheng',
//     // age: 34
// }
// console.log(name, age)

// function foo(){
//     console.log(123)
// }
// let [a = foo()] = []

// function foo([a, b, c]) {
//     console.log(a, b, c)
// }
// let arr = [1, 2, 3]
// foo(arr)

// function foo({name, age, school = 'imooc'}) {
//     console.log(name, age, school)
// }
// let obj = {
//     name: 'xiecheng',
//     age: 34,
//     school: 'xxx'
// }
// foo(obj)

// function foo() {
//     let obj = {
//         name: 'xiecheng',
//         age: 34,
//         school: 'xxx'
//     }
//     return obj
// }
// let {name, age} = foo()
// console.log(name, age)

// json
let json = '{"a": "hello", "b": "world"}'
let {a, b}= JSON.parse(json)
console.log(a, b)

模版字符编码
// unicode
// es6 \uxxxx 码点 0000~ffff
// \u20BB7 -> \u20BB+7
// \u{20BB7}
// \u{41} -> A

// z
// console.log('\z' === 'z')
//  \HHH
// console.log('\172' === 'z')

// \xHH \x7A

// \u007A
// \u{7A}

// for(let item of 'imooc'){
//     console.log(item)
// }

// 模板字符串
// const str1 = '阿斯顿发斯\n'
// + '蒂芬阿萨德法师法\n'
// + '师按时发顺丰'
// console.log(str1);

// const str3 = `阿斯顿发斯
// 蒂芬阿萨德法师法
// 师按时发顺丰`
// console.log(str3);

// const str4 = `
// <ul>
//     <li>1</li>
//     <li>2</li>
//     <li>3</li>
// </ul>
// `
// console.log(str4)

// const a = 20
// const b = 14
// const c = 'ES'
// const str2 = '我的年龄是:' + (a + b) + ',我在讲' + c
// console.log(str2)
// const str5 = `我的年龄是:${a+b},我在讲${c}`
// console.log(str5)

// 嵌套模板
// const isLargeScreen = () => {
//     return true
// }
// let class1 = 'icon'
// class1 += isLargeScreen() ? ' icon-big':' icon-small'
// console.log(class1)

// const class2 = `icon icon-${isLargeScreen()?'big':'small'}`
// console.log(class2)

// 带标签的模板字符串
// const foo = (a, b, c, d) => {
//     console.log(a)
//     console.log(b)
//     console.log(c)
//     console.log(d)
// }
// // foo(1, 2, 3, 4)
// const name = 'xiecheng'
// const age = 34
// foo`这是${name},他的年龄是${age}岁`

// console.log(String.fromCharCode(0x20BB7)) // ES5
// console.log(String.fromCodePoint(0x20BB7)) // ES6

// indexOf


startsWith判断开头
const str = 'imooc'
// console.log(str.indexOf('mo1'))
// console.log(str.includes('mo1'))
// console.log(str.startsWith('im'))
// console.log(str.endsWith('mooc'))
const newStr = str.repeat(10)
console.log(newStr)
深拷贝
// let target = {
//     a: {
//         b: {
//             c: 1
//         },
//         e: 4,
//         f: 5,
//         g: 6
//     }
// }
// let source = {
//     a: {
//         b: {
//             c: 1
//         },
//         e: 2,
//         f: 3
//     }
// }
// Object.assign(target, source)
// console.log(target)

// let a = 5
// let b = a
// a = 6
// console.log(a, b)
// let obj1 = {
//     name: 'xiecheng',
//     age: 34
// }
// let obj2 = obj1
// obj1.age = 18
// console.log(obj1)
// console.log(obj2)

// let obj1 = {
//     name: 'xiecheng',
//     age: 34
// }
// '{"a": "hello", "b": "world"}'
// 
// let obj = JSON.parse('{"a": "hello", "b": "world"}')
// console.log(obj)
// let str = JSON.stringify(obj)
// console.log(str)
// let str = JSON.stringify(obj1)
// let obj2 = JSON.parse(str)
// obj1.age = 18
// console.log(obj2)

// 检查类型
let checkType = data => {
    return Object.prototype.toString.call(data).slice(8, -1)
}
checkType({})

let deepClone = target => {
    let targetType = checkType(target)
    let result
    if (targetType === 'Object') {
        result = {}
    } else if (targetType === 'Array') {
        result = []
    } else {
        return target
    }
    for (let i in target) {
        let value = target[i]
        let valueType = checkType(value)
        if (valueType === 'Object' || valueType === 'Array') {
            result[i] = deepClone(value) // 递归
        } else {
            result[i] = value
        }
    }
    return result
}
// let arr1 = [1, 2, {age: 18}]
// let arr2 = deepClone(arr1)
// arr2[2].age = 34
// console.log(arr1)

let obj1 = {
    name: 'xiecheng',
    hobby: ['coding', 'eating']
}
let obj2 = deepClone(obj1)
obj2.hobby[0] = 'sleeping'
console.log(obj1)
console.log(obj2)
数组
// let s = new Set()
// console.log(s)
// 唯一的
// let s = new Set([1, 2, 3, 2])
// s.add('imooc').add('es')
// s.delete(2)
// s.clear()
// console.log(s.has('imooc'))
// console.log(s)
// console.log(s.size)

// 遍历
// s.forEach(item => console.log(item))
// for (let item of s) {
//     console.log(item)
// }
// for (let item of s.keys()) {
//     console.log(item)
// }
// for (let item of s.values()) {
//     console.log(item)
// }
// for (let item of s.entries()) {
//     console.log(item[0], item[1])
// }

// 数组去重
// let arr = [1, 2, 3, 4, 2, 3]
// let s = new Set(arr)
// console.log(s)

// 合并去重 set->array
// let arr1 = [1, 2, 3, 4]
// let arr2 = [2, 3, 4, 5, 6]
// // let s = new Set([...arr1, ...arr2])
// // console.log(s)
// // console.log([...s])
// // console.log(Array.from(s))

// // 交集
// let s1 = new Set(arr1)
// let s2 = new Set(arr2)
// // let result = new Set(arr1.filter(item => s2.has(item)))
// // console.log(Array.from(result))

// // 差集
// let arr3 = new Set(arr1.filter(item => !s2.has(item)))
// let arr4 = new Set(arr2.filter(item => !s1.has(item)))
// // console.log(arr3)
// // console.log(arr4)
// console.log([...arr3, ...arr4])

// WeakSet
let ws = new WeakSet()
const obj1 = {
    name: 'imooc'
}
const obj2 = {
    age: 5
}
ws.add(obj1)
ws.add(obj2)
// ws.delete(obj1)
// console.log(ws)
// console.log(ws.has(obj2))
// ws.forEach(item => console.log(item))

// 垃圾回收机制 GC +1 +1
// weakset 弱引用
数组方法
let arr = [1, 2, 3, 2, 4]

// for
// for (let i = 0; i < arr.length; i++) {
//     if(arr[i] == 2){
//         continue
//     }
//     console.log(arr[i])
// }

// // forEach
// arr.forEach(function(elem, index, array){
//     if(arr[i] == 2){
//         continue
//     }
//     console.log(elem, index)
// })

// map
// let result = arr.map(function(value){
//     value += 1
//     // console.log(value)
//     return value
// })
// console.log(arr, result)

// filter
// let result = arr.filter(function (value) {
//     // console.log(value)
//     return value == 2
// })
// console.log(arr, result)

// some
// let result = arr.some(function (value) {
//     // console.log(value)
//     return value == 4
// })
// console.log(arr, result)

// every
// let result = arr.every(function (value) {
//     // console.log(value)
//     return value == 2
// })
// console.log(arr, result)

// reduce
// let sum = arr.reduce(function(prev, cur, index, array){
//     return prev + cur
// }, 0)
// console.log(sum)
// let max = arr.reduce(function(prev, cur){
//     return Math.max(prev, cur)
// })
// console.log(max)

// let res = arr.reduce(function(prev, cur){
//     prev.indexOf(cur) == -1 && prev.push(cur)
//     return prev
// }, [])
// console.log(res)

// Array.prototype.foo = function(){
//     console.log('foo')
// }
// for(let index in arr){
//     console.log(index, arr[index])
// }

// // find
// let res = arr.find(function (value) {
//     return value == 8
// })
// console.log(arr, res)

// findIndex
// let res = arr.findIndex(function (value) {
//     return value == 2
// })
// console.log(arr, res)

// for of
// for(let item of arr){
//     console.log(item)
// }

// for(let item of arr.values()){
//     console.log(item)
// }

// for(let item of arr.keys()){
//     console.log(item)
// }

for(let [index, item] of arr.entries()){
    console.log(index, item)
}

数组方法扩展
// // DOM
// let divs = document.getElementsByTagName('div')
// console.log(divs) // HTMLCollection

// let divs2 = document.getElementsByClassName('xx')
// console.log(divs2) // HTMLCollection

// let divs3 = document.querySelectorAll('.xx')
// console.log(divs3 instanceof Array) // NodeList
// // divs3.push(123)

// // slice
// let arr = Array.prototype.slice.call(divs3)
// console.log(arr)
// arr.push(123)
// console.log(arr)

// function foo(){
//     console.log(arguments instanceof Array)
// }
// foo(1, 'imooc', true)

// let arrayLike = {
//     0: 'es6',
//     1: 'es7',
//     2: 'es8',
//     length: 3
// }
// let arr = Array.from(arrayLike)
// arr.push('es9')
// console.log(arr)

// let arr = new Array(1, 2)
// console.log(arr)

// let arr = new Array(3)
// console.log(arr)

// let arr = Array.of(1, 2)
// console.log(arr)

// let arr = Array.of(3)
// console.log(arr)

// let arr = Array.of(1, true, 'imooc', [1, 2, 3], {
//     name: 'xiecheng'
// })
// console.log(arr)

// let arr = [1, 2, 3, 4, 5]
// console.log(arr.copyWithin(1, 3))

// let arr = new Array(3).fill(7)
// console.log(arr)

// let arr = [1, 2, 3, 4, 5]
// // arr.fill('imooc', 1, 3)
// arr.fill(0)
// console.log(arr)

let arr = [1, 2, 3, NaN]
// console.log(arr.indexOf(NaN))
// console.log(NaN == NaN)
console.log(arr.includes(NaN))
异步
// const a = 2
// const b = 3
// console.log(a + b) // 同步任务
// // 异步任务
// setTimeout(() => {
//     console.log(a + b)
// }, 1000)

// 前后端数据分离   前端 <->  后端  ajax
// console.log(1)
// setTimeout(() => {
//     console.log(2)
// }, 1000)
// console.log(3)

// 1 3 2
// console.log(1)
// setTimeout(() => {
//     console.log(2)
// }, 0)
// console.log(3)

// 伪代码
// setTimeout(()=>{
//     task() // 表示一个任务
// }, 2000)
// sleep(5000) // 表示一个很复杂的同步任务


// Ajax的原理
function ajax(url, callback) {
    // 1、创建XMLHttpRequest对象
    var xmlhttp
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest()
    } else { // 兼容早期浏览器
        xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
    }
    // 2、发送请求
    xmlhttp.open('GET', url, true)
    xmlhttp.send()
    // 3、服务端响应
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
            var obj = JSON.parse(xmlhttp.responseText)
            // console.log(obj)
            callback(obj)
        }
    }
}

// var url = 'http://musicapi.xiecheng.live/personalized'
// ajax(url, res => {
//     console.log(res)
// })

// 1 -> 2 -> 3
// callback hell
ajax('static/a.json', res => {
    console.log(res)
    ajax('static/b.json', res => {
        console.log(res)
        ajax('static/c.json', res => {
            console.log(res)
        })
    })
})
正则相关
// i(忽略大小写) m(多行匹配) g(全局匹配)
// y修饰符 粘连(sticky)修饰符
// const str = 'aaa_aa_a'
// const reg1 = /a+/g // 每次匹配剩余的
// const reg2 = /a+/y // 剩余的第一个开始匹配

// console.log(reg1.exec(str))
// console.log(reg2.exec(str))

// console.log(reg1.exec(str)) // aa
// console.log(reg2.exec(str)) // null

// console.log(reg1.exec(str))
// console.log(reg2.exec(str))

// u修饰符 unicode
// \u0000~\uffff
const str = '\uD842\uDFB7' // 表示一个字符
console.log(/^\uD842/.test(str)) // es5 true
console.log(/^\uD842/u.test(str)) // es6 false

// .除了换行符以外的任意单个字符
console.log(/^.$/.test(str)) // false
console.log(/^.$/u.test(str)) // true

console.log(/\u{61}/.test('a')) // false
console.log(/\u{61}/u.test('a')) // true

console.log(/𠮷{2}/.test('𠮷𠮷')) // false
console.log(/𠮷{2}/u.test('𠮷𠮷')) // true


字符串新增方法
// // 十进制 -> 二进制
// const a = 5 // 101
// console.log(a.toString(2))

// // 二进制 -> 十进制
// const b = 101
// // console.log(parseInt(5.5))
// console.log(parseInt(b, 2))

// ES6 0B二进制  0O八进制
// const a = 0B0101
// console.log(a)

// const b = 0O777
// console.log(b)

// console.log(Number.isFinite(5))
// console.log(Number.isFinite(0.5))
// console.log(Number.isFinite(Infinity)) // false
// console.log(Number.isFinite('imooc')) // false
// console.log(Number.isFinite(true)) // false

// NaN:not a number
// console.log(Number.isNaN(NaN)) // true
// console.log(Number.isNaN(15)) // false


// console.log(Number.parseInt(5.5))
// console.log(Number.parseFloat(5.5))
// console.log(window.parseInt(5.5))
// console.log(window.parseFloat(5.5))

// console.log(Number.isInteger(5))
// console.log(Number.isInteger(5.5))

// IEEE 754 双精度标准

// 35 -> 00100011
// 0.375 -> 0.011
// 0.1 -> 0.000110011....
// console.log(0.1000000000000001)
// console.log(0.10000000000000001 === 0.1) // true

// const max = Math.pow(2, 53)
// console.log(max)
// // console.log(max + 1)
// console.log(Number.MAX_SAFE_INTEGER === max - 1)
// console.log(Number.MIN_SAFE_INTEGER)
// console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER))
// console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1))

// console.log(Math.trunc(5.5))
// console.log(Math.trunc(-5.5))
// console.log(Math.trunc(true)) // 1
// console.log(Math.trunc(false)) // 0
// console.log(Math.trunc(NaN)) // NaN
// console.log(Math.trunc(undefined)) // NaN
// console.log(Math.trunc()) // NaN

// console.log(Number.parseInt(5.5))
// console.log(Number.parseInt(-5.5))
// console.log(Number.parseInt(true)) // NaN

// console.log(Math.sign(5)) // 1
// console.log(Math.sign(-5)) // -1
// console.log(Math.sign(0)) // 0
// console.log(Math.sign(NaN)) // NaN
// console.log(Math.sign(true)) // 1
// console.log(Math.sign(false)) // 0

console.log(Math.cbrt(8))
console.log(Math.cbrt('imooc')) // NaN


// includes -> boolean
// const arr = ['es6', 'es7', 'es8']
// console.log(arr.includes('es7'))
// console.log(arr.includes('es9'))
// console.log(arr.includes('es7', 1))
// console.log(arr.includes('es7', 2))
// console.log(arr.includes('es7', -1))
// console.log(arr.includes('es7', -2))

// console.log(arr.indexOf('es7'))
// console.log(arr.indexOf('es7') > -1)

// const arr = ['es6', ['es7', 'es8'], 'es9']
// console.log(arr.includes(['es7', 'es8'])) // false
// console.log(arr.indexOf(['es7', 'es8'])) // -1

const arr = ['es6', 'es7', NaN, 'es8', 2]
// console.log(arr.includes(NaN)) // true
// console.log(arr.indexOf(NaN)) // -1

console.log(arr.includes('2')) // false
console.log(arr.indexOf('2')) // -1

// 2 10 -> 1024
// function pow(x, y) {
//     let res = 1
//     for (let i = 0; i < y; i++) {
//         res *= x
//     }
//     return res
// }
// console.log(pow(2, 10))

// console.log(Math.pow(2, 10))

console.log(2 ** 10)
Promise
// let p1 = Promise.resolve('success')
// // console.log(p1)
// p1.then(res => {
//     console.log(res)
// })

// let p2 = Promise.reject('fail')
// console.log(p2)
// p2.catch(err => {
//     console.log(err)
// })

// function foo(flag) {
//     if (flag) {
//         return new Promise(resolve => {
//             // 异步操作
//             resolve('success')
//         })
//     } else {
//         // return 'fail'
//         return Promise.reject('fail')
//     }
// }

// foo(false).then(res => {
//     console.log(res)
// }, err => {
//     console.log(err)
// })

// let p1 = new Promise((resolve, reject) => {
//     setTimeout(() => {
//         console.log(1)
//         resolve('1成功')
//     }, 2000)
// })
// let p2 = new Promise((resolve, reject) => {
//     setTimeout(() => {
//         console.log(2)
//         // resolve('2成功')
//         reject('2失败')
//     }, 1000)
// })
// let p3 = new Promise((resolve, reject) => {
//     setTimeout(() => {
//         console.log(3)
//         resolve('3成功')
//     }, 3000)
// })

// Promise.all([p1, p2, p3]).then(res => {
//     console.log(res)
// }, err => {
//     console.log(err)
// })
// Promise.race([p1, p2, p3]).then(res => {
//     console.log(res)
// }, err => {
//     console.log(err)
// })

const imgArr = ['1.jpg', '2.jpg', '3.jpg']
let promiseArr = []
imgArr.forEach(item => {
    promiseArr.push(new Promise((resolve, reject) => {
        // 图片上传的操作
        resolve()
    }))
})
Promise.all(promiseArr).then(res => {
    // 插入数据库的操作
    console.log('图片全部上传完成')
})

function getImg() {
    return new Promise((resolve, reject) => {
        let img = new Image()
        img.onload = function () {
            resolve(img)
        }
        // img.src = 'http://www.xxx.com/xx.jpg'
        img.src = 'https://www.imooc.com/static/img/index/logo.png'
    })
}

function timeout() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('图片请求超时')
        }, 2000)
    })
}

Promise.race([getImg(), timeout()]).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

// // 状态管理 
// // resolve 成功
// // reject 失败
// let p = new Promise((resolve, reject) => {
//     setTimeout(() => {
//         console.log('imooc')
//         // resolve()
//         // reject()
//         // if(){
//         //     resolve()
//         // }else{
//         //     reject()
//         // }
//         // resolve('成功')
//         reject('失败')
//     }, 1000)
// }).then(res => {
//     console.log(res)
// }, err => {
//     console.log(err)
// })

// let p = new Promise((resolve, reject) => {
//     console.log(1)
//     resolve()
// })
// console.log(2)
// p.then(res => {
//     console.log(3)
// })

// let p1 = new Promise((resolve, reject) => {
//     resolve(1)
// })
// let p2 = new Promise((resolve, reject) => {
//     setTimeout(() => {
//         resolve(2)
//     }, 1000)
// })
// let p3 = new Promise((resolve, reject) => {
//     setTimeout(() => {
//         reject(3)
//     }, 1000)
// })
// console.log(p1) // resolved
// console.log(p2) // pending
// console.log(p3) // pending
// setTimeout(() => {
//     console.log(p2)
// }, 2000)
// setTimeout(() => {
//     console.log(p3)
// }, 2000)

// p1.then(res => {
//     console.log(res)
// })
// p2.then(res => {
//     console.log(res)
// })
// p3.catch(err => {
//     console.log(err)
// })

// let p = new Promise((resolve, reject) => {
//     reject(2)
//     resolve(1)
// })
// p.then(res => {
//     console.log(res)
// }).catch(err => {
//     console.log(err)
// })

function ajax(url, successCallback, failCallback) {
    // 1、创建XMLHttpRequest对象
    var xmlhttp
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest()
    } else { // 兼容早期浏览器
        xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
    }
    // 2、发送请求
    xmlhttp.open('GET', url, true)
    xmlhttp.send()
    // 3、服务端响应
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
            var obj = JSON.parse(xmlhttp.responseText)
            // console.log(obj)
            successCallback && successCallback(obj)
        } else if (xmlhttp.readyState === 4 && xmlhttp.status === 404) {
            failCallback && failCallback(xmlhttp.statusText)
        }
    }
}

// new Promise((resolve, reject) => {
//     ajax('static/a.json', res => {
//         console.log(res)
//         resolve()
//     })
// }).then(res => {
//     console.log('a成功')
//     return new Promise((resolve, reject) => {
//         ajax('static/b.json', res => {
//             console.log(res)
//             resolve()
//         })
//     })
// }).then(res => {
//     console.log('b成功')
//     return new Promise((resolve, reject) => {
//         ajax('static/c.json', res => {
//             console.log(res)
//             resolve()
//         })
//     })
// }).then(res => {
//     console.log('c成功')
// })

function getPromise(url) {
    return new Promise((resolve, reject) => {
        ajax(url, res => {
            resolve(res)
        }, err => {
            reject(err)
        })
    })
}
// getPromise('static/aa.json')
//     .then(res => {
//         console.log(res)
//         return getPromise('static/b.json')
//     }).then(res => {
//         console.log(res)
//         return getPromise('static/c.json')
//     }).then(res => {
//         console.log(res)
//     })
// getPromise('static/aa.json')
//     .then(res => {
//         console.log(res)
//         return getPromise('static/b.json')
//     }, err => {
//         console.log(err)
//         return getPromise('static/b.json')
//     }).then(res => {
//         console.log(res)
//         return getPromise('static/c.json')
//     }).then(res => {
//         console.log(res)
//     })

getPromise('static/a.json')
    .then(res => {
        console.log(res)
        return getPromise('static/b.json')
    }).then(res => {
        console.log(res)
        return getPromise('static/c.json')
    }).then(res => {
        console.log(res)
    }).catch(err => {
        console.log(err)
    })
Reflect
// Object -> Reflect
// let obj = {}
// let newVal = ''
// Reflect.defineProperty(obj, 'name', {
//     get() {
//         return newVal
//     },
//     set(val) {
//         console.log('set')
//         // this.name = val
//         newVal = val
//     }
// })
// obj.name = 'es'
// console.log(obj.name)

// try {
//     Object.defineProperty()
// } catch (e) {}

// if (Reflect.defineProperty()) { // boolean

// } else {

// }

// console.log('assign' in Object) // true
// console.log(Reflect.has(Object, 'assign'))// true

// let user = {
//     name: 'xiecheng',
//     age: 34,
//     _password: '***'
// }
// user = new Proxy(user, {
//     get(target, prop) {
//         if (prop.startsWith('_')) {
//             throw new Error('不可访问')
//         } else {
//             // return target[prop]
//             return Reflect.get(target, prop)
//         }
//     },
//     set(target, prop, val) {
//         if (prop.startsWith('_')) {
//             throw new Error('不可访问')
//         } else {
//             // target[prop] = val
//             Reflect.set(target, prop, val)
//             return true
//         }
//     },
//     deleteProperty(target, prop) { // 拦截删除
//         if (prop.startsWith('_')) {
//             throw new Error('不可删除')
//         } else {
//             // delete target[prop]
//             Reflect.deleteProperty(target, prop)
//             return true
//         }
//     },
//     ownKeys(target) {
//         // return Object.keys(target).filter(key => !key.startsWith('_'))
//         return Reflect.ownKeys(target).filter(key => !key.startsWith('_'))
//     }
// })

// console.log(user.age)
// try {
//     console.log(user._password)
// } catch (e) {
//     console.log(e.message)
// }

// user.age = 18
// console.log(user.age)
// try {
//     user._password = 'xxx'
// } catch (e) {
//     console.log(e.message)
// }

// // delete user.age
// // console.log(user.age)
// for (let key in user) {
//     console.log(key)
// }

// apply
let sum = (...args) => {
    let num = 0
    args.forEach(item => {
        num += item
    })
    return num
}

sum = new Proxy(sum, {
    apply(target, ctx, args) {
        // return target(...args) * 2
        return Reflect.apply(target, target, [...args]) * 2
    }
})
console.log(sum(1, 2))
console.log(sum.call(null, 1, 2, 3))
console.log(sum.apply(null, [1, 2, 3]))

模块化
// export const a = 5
// export const b = 'imooc'
// export const sum = (x, y) => x + y
// const obj = {
//     name: 'es'
// }
// export {obj}

// const a = 5
// const b = 'imooc'
// const sum = (x, y) => x + y
// const obj = {
//     name: 'es'
// }

// class People {
//     constructor(name) {
//         this.name = name
//     }
//     showName() {
//         console.log(this.name)
//     }
// }

// export {
//     a,
//     b,
//     sum,
//     obj,
//     People
// }

// const a = 5
// export default a
// const b = 'imooc'
// export default b

// export default const a = 5 // 错误
// function sum(x, y) {
//     return x + y
// }
// export default sum

// export const str = 'imooc'

const a = 5
const b = 'imooc'
const sum = (x, y) => x + y
const obj = {
    name: 'es'
}
class People {
    constructor(name) {
        this.name = name
    }
    showName() {
        console.log(this.name)
    }
}
export default {
    a,
    b,
    sum,
    obj,
    People
}


// import {
//     a as aa,
//     b,
//     sum,
//     obj,
//     People
// } from './module'
// console.log(aa, b)
// console.log(sum(2, 5))
// console.log(obj)
// let p = new People('xiecheng')
// p.showName()

// import add, {str} from './module'
// console.log(add(4, 5), str)


// import mod from './module'
// console.log(mod.a)
// console.log(mod.b)
// console.log(mod.obj)
// console.log(mod.sum(7, 8))

import * as mod from './module'
console.log(mod)
console.log(mod.default.a)
console.log(mod.default.b)
console.log(mod.default.sum(8, 9))
rest扩展运算符
// export const a = 5
// export const b = 'imooc'
// export const sum = (x, y) => x + y
// const obj = {
//     name: 'es'
// }
// export {obj}

// const a = 5
// const b = 'imooc'
// const sum = (x, y) => x + y
// const obj = {
//     name: 'es'
// }

// class People {
//     constructor(name) {
//         this.name = name
//     }
//     showName() {
//         console.log(this.name)
//     }
// }

// export {
//     a,
//     b,
//     sum,
//     obj,
//     People
// }

// const a = 5
// export default a
// const b = 'imooc'
// export default b

// export default const a = 5 // 错误
// function sum(x, y) {
//     return x + y
// }
// export default sum

// export const str = 'imooc'

const a = 5
const b = 'imooc'
const sum = (x, y) => x + y
const obj = {
    name: 'es'
}
class People {
    constructor(name) {
        this.name = name
    }
    showName() {
        console.log(this.name)
    }
}
export default {
    a,
    b,
    sum,
    obj,
    People
}
Set.map
// let m = new Map()
// let obj = {
//     name: 'imooc'
// }
// m.set(obj, 'es')
// console.log(m.get(obj))
// m.delete(obj)
// console.log(m)
// console.log(m.has(obj))

let map = new Map([
    ['name', 'imooc'],
    ['age', 5]
])
// console.log(map.size)
// console.log(map.has('name'))
// console.log(map.get('age'))
// map.set('name', 'zhangsan')
// map.delete('name')
// console.log(map)

// 遍历
// map.forEach((value, key) => console.log(value, key))

// for(let [key, value] of map){
//     console.log(key, value)
// }

// for(let key of map.keys()){
//     console.log(key)
// }

// for(let value of map.values()){
//     console.log(value)
// }

// for(let [key, value] of map.entries()){
//     console.log(key, value)
// }

// map  object

// weakmap
// let wm = new WeakMap()
// wm.set([1], 2)
// wm.set({
//     name: 'imooc'
// }, 'es')
// // wm.clear()
// console.log(wm.size)

let wm = new WeakMap()
let elem = document.getElementsByTagName('h1')
wm.set(elem, 'info')
console.log(wm.get(elem))
Symbol
// let s1 = Symbol()
// let s2 = Symbol()
// console.log(s1)
// console.log(s2)
// console.log(s1 === s2) // false

// let s1 = Symbol('foo')
// let s2 = Symbol('bar')
// console.log(s1)
// console.log(s2)
// console.log(s1 === s2)// false

// const obj = {
//     name: 'imooc',
//     toString() {
//         return this.name
//     }
// }
// let s = Symbol(obj)
// console.log(s)

// let s = Symbol('foo')
// // s.name = 'imooc'
// // console.log(s)
// console.log(s.description)

// let s1 = Symbol.for('foo')
// let s2 = Symbol.for('foo')
// console.log(s1 === s2) // true

// function foo() {
//     return Symbol.for('foo')
// }
// const x = foo()
// const y = Symbol.for('foo')
// console.log(x === y) // true

// const s1 = Symbol('foo')
// console.log(Symbol.keyFor(s1)) // undefined

// const s2 = Symbol.for('foo')
// console.log(Symbol.keyFor(s2)) // foo

// const grade = {
//     张三: {address: 'xxx', tel: '111'},
//     李四: {address: 'yyy', tel: '222'},
//     李四: {address: 'zzz', tel: '333'},
// }
// console.log(grade)

// const stu1 = '李四'
// const stu2 = '李四'
// const grade = {
//     [stu1]: {address: 'yyy', tel: '222'},
//     [stu2]: {address: 'zzz', tel: '333'},
// }
// console.log(grade)

// const stu1 = Symbol('李四')
// const stu2 = Symbol('李四')
// const grade = {
//     [stu1]: {address: 'yyy', tel: '222'},
//     [stu2]: {address: 'zzz', tel: '333'},
// }
// console.log(grade)
// console.log(grade[stu1])
// console.log(grade[stu2])

const sym = Symbol('imooc')
class User {
    constructor(name) {
        this.name = name
        this[sym] = 'imooc.com'
    }
    getName() {
        return this.name + this[sym]
    }
}
const user = new User('xiecheng')
// console.log(user.getName())

// for(let key in user){
//     console.log(key)
// }

// for(let key of Object.keys(user)){
//     console.log(key)
// }

// for(let key of Object.getOwnPropertySymbols(user)){
//     console.log(key)
// }

// for(let key of Reflect.ownKeys(user)){
//     console.log(key)
// }

// function getArea(shape) {
//     let area = 0
//     switch (shape) {
//         case 'Triangle':
//             area = 1
//             break
//         case 'Circle':
//             area = 2
//             break
//     }
//     return area
// }
// console.log(getArea('Triangle'))

const shapeType = {
    triangle: Symbol(),
    circle: Symbol()
}
function getArea(shape) {
    let area = 0
    switch (shape) {
        case shapeType.triangle:
            area = 1
            break
        case shapeType.circle:
            area = 2
            break
    }
    return area
}
console.log(getArea(shapeType.triangle))
Ajax
function ajax(url, callback) {
    // 1、创建XMLHttpRequest对象
    var xmlhttp
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest()
    } else { // 兼容早期浏览器
        xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
    }
    // 2、发送请求
    xmlhttp.open('GET', url, true)
    xmlhttp.send()
    // 3、服务端响应
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
            var obj = JSON.parse(xmlhttp.responseText)
            // console.log(obj)
            callback(obj)
        }
    }
}
export default ajax
next()函数 Iterator
// function foo() {
//     for (let i = 0; i < 3; i++) {
//         console.log(i)
//     }
// }
// foo()

// function* foo() {
//     for (let i = 0; i < 3; i++) {
//         yield i
//     }
// }
// // console.log(foo())
// let f = foo()
// console.log(f.next())
// console.log(f.next())
// console.log(f.next())
// console.log(f.next())

// function* gen(args) {
//     args.forEach(item => {
//         yield item + 1
//     })
// }

// function* gen(x) {
//     let y = 2 * (yield(x + 1))
//     let z = yield(y / 3)
//     return x + y + z
// }
// let g = gen(5)
// console.log(g.next()) // 6
// console.log(g.next()) // NaN
// console.log(g.next()) // NaN

// let g = gen(5)
// console.log(g.next()) // 6
// console.log(g.next(12)) // y=24  8
// console.log(g.next(13)) // z=13 x=5 42

// function* count(x = 1) {
//     while (true) {
//         if (x % 7 === 0) {
//             yield x
//         }
//         x++
//     }
// }
// let n = count()
// console.log(n.next().value)
// console.log(n.next().value)
// console.log(n.next().value)
// console.log(n.next().value)
// console.log(n.next().value)

function ajax(url, callback) {
    // 1、创建XMLHttpRequest对象
    var xmlhttp
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest()
    } else { // 兼容早期浏览器
        xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
    }
    // 2、发送请求
    xmlhttp.open('GET', url, true)
    xmlhttp.send()
    // 3、服务端响应
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
            var obj = JSON.parse(xmlhttp.responseText)
            // console.log(obj)
            callback(obj)
        }
    }
}

function request(url) {
    ajax(url, res => {
        getData.next(res)
    })
}

function* gen() {
    let res1 = yield request('static/a.json')
    console.log(res1)
    let res2 = yield request('static/b.json')
    console.log(res2)
    let res3 = yield request('static/c.json')
    console.log(res3)
}
let getData = gen()
getData.next()


function makeIterator(arr) {
//     let nextIndex = 0
//     return {
//         next() {
//             return nextIndex < arr.length ? {
//                 value: arr[nextIndex++],
//                 done: false
//             } : {
//                 value: undefined,
//                 done: true
//             }
//         }
//     }
// }
// let it = makeIterator(['a', 'b', 'c'])
// console.log(it.next())
// console.log(it.next())
// console.log(it.next())
// console.log(it.next())

// for(let c of courses){
//     console.log(c)
// }
// let arr = ['a', 'b', 'c']
// console.log(arr)
// let it = arr[Symbol.iterator]()
// console.log(it.next())
// console.log(it.next())
// console.log(it.next())
// console.log(it.next())

// let map = new Map()
// map.set('name', 'es')
// map.set('age', 5)
// map.set('school', 'imooc')
// // console.log(map)
// let it = map[Symbol.iterator]()
// console.log(it.next())
// console.log(it.next())
// console.log(it.next())
// console.log(it.next())


let courses = {
    allCourse: {
        frontend: ['ES', '小程序', 'Vue', 'React'],
        backend: ['Java', 'Python', 'SpringBoot'],
        webapp: ['Android', 'IOS']
    }
}

// 可迭代协议:Symbol.iterator
// 迭代器协议:return { next(){ return{value, done} }}
// courses[Symbol.iterator] = function () {
//     let allCourse = this.allCourse
//     let keys = Reflect.ownKeys(allCourse)
//     let values = []
//     return {
//         next() {
//             if (!values.length) {
//                 if (keys.length) {
//                     values = allCourse[keys[0]]
//                     keys.shift()
//                 }
//             }
//             return {
//                 done: !values.length,
//                 value: values.shift()
//             }
//         }
//     }
// }

// for (let c of courses) {
//     console.log(c)
// }

// generator
courses[Symbol.iterator] = function* () {
    let allCourse = this.allCourse
    let keys = Reflect.ownKeys(allCourse)
    let values = []
    while (1) {
        if (!values.length) {
            if (keys.length) {
                values = allCourse[keys[0]]
                keys.shift()
                yield values.shift()
            } else {
                return false
            }
        }else{
            yield values.shift()
        }
    }
}
for (let c of courses) {
    console.log(c)
}
Async await
// function foo() {
//     return 'imooc'
// }
// console.log(foo())

// async function foo(){
//     return 'imooc' // Promise.resolve('imooc')
// }
// console.log(foo())

// async function foo() {
//     let result = await 'imooc'
//     console.log(result)
// }
// foo()

// function timeout() {
//     return new Promise(resolve => {
//         setTimeout(()=>{
//             // console.log(1)
//             resolve(1)
//         }, 1000)
//     })
// }

// async function foo(){
//     const res = await timeout()
//     console.log(res)
//     console.log(2)
// }
// foo()

// function timeout() {
//     return new Promise((resolve, reject) => {
//         setTimeout(() => {
//             // resolve('success')
//             reject('fail')
//         }, 1000)
//     })
// }
// async function foo() {
//     return await timeout()
// }
// foo().then(res => {
//     console.log(res);
// }).catch(err => {
//     console.log(err)
// })

// 伪代码
// async function request(){
//     const data = await axios.get('http://www.xx.com')
//     console.log(data)
// }

import ajax from './ajax'

function request(url) {
    return new Promise(resolve => {
        ajax(url, res => {
            resolve(res)
        })
    })
}
async function getData(){
    const res1 = await request('static/a.json')
    console.log(res1)
    const res2 = await request('static/b.json')
    console.log(res2)
    const res3 = await request('static/c.json')
    console.log(res3)
}
getData()
const obj = {
    name: 'imooc',
    web: 'www.imooc.com',
    course: 'es'
}
// console.log(Object.keys(obj))
// const res = Object.keys(obj).map(key => obj[key])
// console.log(res)

// console.log(Object.values(obj))
// console.log(Object.entries(obj))
// for(let [key, val] of Object.entries(obj)){
//     console.log(`${key}: ${val}`)
// }
console.log(Object.entries(['a', 'b', 'c']))