js中的一些基础语法整理

this 指向

普通函数

const teacher = {
    name: 'xiaoming',
getName: function() { return `${this.name}`
} }
console.log(teacher.getName());// xiaoming

普通函数谁调用,函数中this就指向谁,teacher调用getName,getName中的this指向teacher

箭头函数

const teacher = {
    name: 'xiaoming',
getName: ()=> { return `${this.name}`
} }
console.log(teacher.getName());// undefined

箭头函数⾥的this是定义的时候决定的,定义的时候 getName的this指向的是window,window 没有name ,所以输出undefine

 var name = '123'
const teacher = {
    name: 'xiaoming',
getName: ()=> { return `${this.name}`
} }
console.log(teacher.getName());// 123

因此箭头函数不能用作构造函数,构造函数需要改变this的指向到新实例例出来的对象,this指向是定义的时候决定的

手写一个模版字符串的实现

const year ='2021'
const month = '04'
const day = '25'
let template = '${year}-${month}-${day}'
let context = {year,month,day}
const str = render(template)(context)
console.log(str)
function render (template){
    return function (context){
        return template.replace(/\$\{(.*?)\}/g,(match,key)=>{
            return context[key]
        })
    }
}// 2021-04-25

结构原理

针对可迭代对象的Iterator接⼝口,通过遍历器器按顺序获取对应的值进⾏行行赋值.
Iterator是⼀一种接⼝口,为各种不不⼀一样的数据解构提供统⼀一的访问机制。任何数据解构只要有 Iterator接⼝口,就能通过遍历操作,依次按顺序处理理数据结构内所有成员。ES6中的for of的语 法相当于遍历器器,会在遍历数据结构时,⾃自动寻找Iterator接⼝口。

手写iterator

function generateiterator(array){
    let nextIndex = 0
    return {
       next:()=>{
           return nextIndex<array.length ? {value:array[nextIndex++],done:false}:{value:undefined,done:true}
       }
    }
}
const iterator = generateiterator([3,4,5])
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
/*
{ value: 3, done: false }
{ value: 4, done: false }
{ value: 5, done: false }
{ value: undefined, done: true }
*/

可迭代对象是什什么?

可迭代对象是Iterator接⼝口的实现。这是ECMAScript 2015的补充,它不不是内置或语法,⽽而仅 仅是协议。任何遵循该协议点对象都能成为可迭代对象。可迭代对象得有两个协议:可迭代协 议和迭代器器协议。
可迭代协议:对象必须实现iterator⽅方法。即对象或其原型链上必须有⼀一个名叫 Symbol.iterator的属性。该属性的值为⽆无参函数,函数返回迭代器器协

⾃己来实现一个可以for of遍历的对象

通过以上可知,自定义数据结构,只要拥有Iterator接口,并将其部署到⾃己的
Symbol.iterator属性上,就可以成为可迭代对象,能被for of循环遍历.

const obj={
    count:0,
    [Symbol.iterator]:()=>{
        return {
            next:()=>{
                if(obj.count<10){
                    return {value:obj.count++,done:false}
                }else{
                    return {value:undefined,done:true}
                }
            }
        }
    }
}

for (const item of obj){
    console.log(item)
}
/*
0
1
2
3
4
5
6
7
8
9
*/
const iterable={
    0:'a',
    1:'b',
    2:'c',
    length:3,
    [Symbol.iterator]:Array.prototype[Symbol.iterator]
};
for (const item of iterable){
    console.log(item)
}
/*
a
b
c
*/

遍历

1.for in 与 for of
遍历数组时,key为数组下标字符串串;遍历对象,key为对象字段名。
缺点:
for in 不不仅会遍历当前对象,还包括原型链上的可枚举属性
for in 不不适合遍历数组,主要应⽤用为对象

for of 仅遍历当前对象

let obj = {a: 'test1', b: 'test2'}
Object.prototype.name='小明'
for (let key in obj) {
console.log(key, obj[key]) } 
/*
a test1
b test2
name 小明
*/
let arr = [3,4,5,6,7]
Array.prototype.text = '123'
for (item in arr){
    console.log(item) // 0 1 2 3 4 text
}

let arr = [3,4,5,6,7]
Array.prototype.text = '123'
for (item of arr){
    console.log(item) // 3 4 5 6 7
}

for in 遍历的是数组索引
for of 遍历的是数组中内容

let arr = [3,4,5,6,7]
for (item in arr){
    console.log(item) // 0 1 2 3 4
}

let arr = [3,4,5,6,7]
for (item of arr){
    console.log(item) // 3,4,5,6,7
}

for of 可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments对象,NodeList对 象)上创建⼀一个迭代循环,调⽤用⾃自定义迭代钩⼦子,并为每个不不同属性的值执⾏行行语句句。

let arr = [{ age: 1 }, { age: 5 }, { age: 100 }, { age: 34 }]
for (let { age } of arr) {
    if (age > 10) {
        break
    }
    console.log(age) // 1 5
}

手写object.keys

function getObjectKeys(obj){
   const result =  []
   for (let key in obj){
       if (obj.hasOwnProperty(key)){
           result.push(key)
       }
   }
   return result
}
console.log(getObjectKeys({
    a:1,b:2
})) // [ 'a', 'b' ]

手写 object.values

function getObjectValues(obj){
   const result =  []
   for (let key in obj){
       if (obj.hasOwnProperty(key)){
           result.push(obj[key])
       }
   }
   return result
}
console.log(getObjectValues({
    a:1,b:2
})) // [ 1, 2 ]

手写 object.entries

   const result =  []
   for (let key in obj){
       if (obj.hasOwnProperty(key)){
           result.push([key,obj[key]])
       }
   }
   return result
}
console.log(getObjectEntries({
    a:1,b:2
})) // [ [ 'a', 1 ], [ 'b', 2 ] ]

Object.getOwnPropertyNames
该⽅方法返回一个数组,该数组对元素是 obj⾃自身拥有的枚举或不不可枚举属性名称字符串串。

Object.prototype.aa = '1111'
const testData={
    a:1,
    b:2
}
for (const key in testData){
    console.log(key) // a b aa
}
console.log(Object.getOwnPropertyNames(testData)) // [ 'a', 'b' ]

Object.create()

Object.create()方法创建一个新的对象,并以方法的第一个参数作为新对象的proto属性的值 (根据已有的对象作为原型,创建新的对象。) Object.create()方法还有第二个可选参数,是一个对象,对象的每个属性都会作为新对象的自身属性,对象的属性值以descriptor(Object.getOwnPropertyDescriptor(obj, ‘key’))的形式 出现,且enumerable默认为false

const person ={
    isHuman:false,
    printIntroduction:function(){
        console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`)
    }
}
const me = Object.create(person);
me.name='1234'
me.isHuman = true
me.printIntroduction() // My name is 1234. Am I human? true
console.log(person) // { isHuman: false, printIntroduction: [Function: printIntroduction] }
function Person(name,sex){
    this.name = name;
    this.sex = sex
}
const b = Object.create(Person.prototype,{
    name:{
        value:'coco',
        writable:true,
        configurable:true,
        enumerable:true
    },
    sex:{
        enumerable:true,
        get:function(){
            return 'hello sex'
        },
        set:function(val){
            console.log('~~~~~~~~',this.sex)
            console.log('set value'+val)
        }
    }
})
b.sex = '1233'
console.log(b.name)
console.log(b.sex)
/*
~~~~~~~~ hello sex
set value1233
coco
hello sex
*/

手写promiseAll


function PromiseAll(proArr){
    return new Promise((resolve,reject)=>{
        if (!Array.isArray(proArr)){
            return reject(new TypeError('必须是一个数组'))
        }else{
            let count = 0 ,length = proArr.length,resolveArr = []
            for (let i = 0;i<length;i++){
                Promise.resolve(proArr[i]).then(value=>{
                    count++
                    resolveArr[i] = value
                    if (count === length){
                        return resolve(resolveArr)
                    }
                }).catch(e=>reject(e))
            }
        }
    })
}

function PromiseAll2(proArr){
     // 第二种写法
    return new Promise((resolve,reject)=>{
        if (!Array.isArray(proArr)){
            return reject(new TypeError('必须是一个数组'))
        }else{
            let count = 0 ,length = proArr.length,resolveArr = []
            for (let i = 0;i<length;i++){
                Promise.resolve(proArr[i]).then(value=>{
                   
                    resolveArr[i] = value
                   
                }).catch(e=>reject(e)).finally(()=>{
                    count++
                    if (count === length){
                        return resolve(resolveArr)
                    }
                })
            }
        }
    })
}

const pro1 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve(1)
    },1000)
})
const pro2 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve(2)
    },2000)
})

const pro3 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve(3)
    },3000)
})
const proAll = PromiseAll([pro1,pro2,pro3]).then(res=>{
    console.log(res)
}).catch((e)=>{
    console.log(e)
})


手写promiseallsettled

function PromiseAllSettled(promiseArray){
    return new Promise((resolve,reject)=>{
        if(!Array.isArray(promiseArray)){
            return reject(new TypeError('必须是一个数组'))
        }
        let counter = 0
        const length = promiseArray.length
        const reseloveArray = []
        for(let i = 0;i<length;i++){
            Promise.resolve(promiseArray[i]).then(value=>{
                reseloveArray[i]={
                    status:'fulfilled',
                    value
                }
            }).catch(reason=>{
                reseloveArray[i]={
                    status:'rejected',
                    reason
                }
            }).finally(()=>{
                counter++
                if(counter === length){
                    resolve(reseloveArray)
                }
            })
        }
    })
}



const pro1 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve(1)
    },1000)
})
const pro2 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve(2)
    },2000)
})

const pro3 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve(3)
    },3000)
})
const proAll = PromiseAllSettled([pro1,pro2,pro3]).then(res=>{
    console.log(res)
}).catch((e)=>{
    console.log(e)
})
/*
[
  { status: 'fulfilled', value: 1 },
  { status: 'fulfilled', value: 2 },
  { status: 'fulfilled', value: 3 }
]
*/

手写 flat 打平数组

const arr1 = [1,2,3,[1,2,3,4,[2,3,4,5,6,[7,9,10,12]]]]
function flatDeep(arr,d=1){
    if(d>0){
        return arr.reduce((res,val)=>{
            if (Array.isArray(val)){
                res = res.concat(flatDeep(val,d-1))
            }else{
                res = res.concat(val)
            }
            return res

        },[])
    }else{
        return arr.slice()
    }
}
console.log(flatDeep(arr1,Infinity))
// 没有深度
function faltten(array){
    if(!Array.isArray(array)){
        return new TypeError('必须是数组')
    }
    let length = array.length,resArr = []
    for (let i = 0;i<length;i++){
        if(Array.isArray(array[i])){
            resArr = resArr.concat(faltten(array[i]))
        }else{
            resArr.push(array[i])
        }
    }
    return resArr
}
console.log(faltten([1,2,3,4,[5,6,7,[8,9,10,[11]]]]))


// 如果数组元素都是Number类型
function flatten(arr) {
    return arr.toString().split(',').map(item => Number(item))
 }
    
 console.log(flatten([1,2,3,4,[5,6,7,[8,9,10,[11]]]]))

 function flatten(arr) {
    while(arr.some(item=>Array.isArray(item))){
        arr = [].concat(...arr)
    }
    return arr
 }
    
 console.log(flatten([1,2,3,4,[5,6,7,[8,9,10,[11]]]]))
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容