js中级

152 阅读1分钟
function fn(a, c){
            console.log(a); //f a(){ }
            var a = 123; 
            console.log(a); //123
            console.log(c); //2
            function a(){ };
            if(false){
                var d = 678
            }
            console.log(d); //undefined
            console.log(b); //undefined
            var b = function(){};
            console.log(b); //f (){}
            console.log(c); //2
        }
        fn(1, 2)
        //预编译
        //作用域的创建阶段,预编译的阶段
        //预编译的时候做了哪些事
        //js的变量对象  AO对象 供js引擎自己区访问的
        //预编译过程:
        /*
            1.创建了ao对象 
            2.找形参和变量的声明 作为对象的属性名 值是undefined
            3.实参和形参相统一
            4.找函数声明 会覆盖变量的声明
        */
        AO:{
            a:undefined => 1 => function a(){}
            c:undefined => 2 => function c(){}
            d:undefined
            b:undefined
        }

单例

const loginLayer = function () {
            let div = document.createElement('div')
            div.innerHTML = '我是登录的弹窗'
            div.style.display = 'block'
            document.body.appendChild(div)
            return div
        }
        const getSingle = function (loginLayer) {
            let result
            return function(){
               return  result || (result = loginLayer())
            }
        }
        const fn = getSingle(loginLayer)
        document.getElementById('btn').onclick = fn

策略模式:

初版:

const registerForm = document.getElementById('registerForm')
registerForm.onsubmit=function(){
    if(registerForm.username.value === ''){
        alert("用户名不能为空")
        return false
    }
    if(registerForm.password.value.length<6){
        alert('密码长度不能小于6')
        return false
    }
}

策略模式版:

<body>
    <form action="xxx.com" method='post' id=registerForm>
        请输入用户名:<input type="text" name="username">
        请输入密码:<input type="password" name="password">
        <button>提交</button>
    </form>
    <script>
        const registerForm = document.getElementById('registerForm')
        const strategies = {
            isNonEmpty: function(value, errorMsg){
                if(value === ''){
                    return errorMsg
                }
            },
            isMinLength: function(value,length,errorMsg){
                if(value.length<6){
                    return errorMsg
                }
            }
        }
        const Validator = function(){
            this.cache = []
        }
        Validator.prototype.add = function(dom,rule,errorMsg){
            const ary = rule.split(':')
            this.cache.push(function(){
                const strategy = ary.shift()
                ary.unshift(dom.value)
                ary.push(errorMsg)
                return strategies[strategy](...ary)
            })
        }
        Validator.prototype.start = function(){
            for(let i = 0,vaFunc;vaFunc = this.cache[i++];){
                let msg = vaFunc()
                if(msg) {
                    return msg
                }           
        }}
        const validateFun = function(){
            const validator = new Validator()
            validator.add(registerForm.username, 'isNonEmpty', '用户名不能为空')
            validator.add(registerForm.password, 'isMinLength:6', '密码长度不能小于6')
            const errorMsg = validator.start()
            return errorMsg
        }
        registerForm.onsubmit = function(){
            const errorMsg = validateFun()
            if(errorMsg){
                alert(errorMsg)
                return false
            }
        }
    </script>
</body>

发布订阅模式

const shopObj = {}

        shopObj.list = []

        shopObj.listen = function(key, fn){
            if(!this.list[key]){
                this.list[key] = []
            }
            this.list[key].push(fn)
        }

        shopObj.trigger = function(){
            const key = Array.prototype.shift.call(arguments)
            let fn
            let fns = this.list[key]
            if(!fns || fns.length ===0 ){
                return
            }
            for(let i = 0;fn = fns[i];i++){
                fn(...arguments)
            }
        }
        shopObj.listen('red',function(size){
            console.log(`尺寸是${size}`);
        })
        shopObj.listen('black',function(size){
            console.log(`再次尺寸是${size}`);
        })
        shopObj.trigger('red',42)
        shopObj.trigger('black',40)

精简版:

const event = {
            list: [],
            listen: function (key, fn) {
                if (!this.list[key]) {
                    this.list[key] = []
                }
                this.list[key].push(fn)
            },
            trigger: function () {
                const key = Array.prototype.shift.call(arguments)
                let fn
                let fns = this.list[key]
                if (!fns || fns.length === 0) {
                    return
                }
                for (let i = 0; fn = fns[i]; i++) {
                    fn(...arguments)
                }
            }
        }
        event.listen('red', function (size) {
            console.log(`尺寸是${size}`);
        })
        event.trigger('red',40)

数组扁平化:

将[0,1,2,[0,1,2,[6,7,8]]]变成一维数组

const num = [0,1,2,[0,1,2,[6,7,8]]]
num.flat(Infinity)
const num = [0,1,2,[0,1,2,[6,7,8]]]
        const res = []
        const arr = item=>{
            for(let i = 0;i<item.length;i++){
                if(Array.isArray(item[i])){
                     arr(item[i]) 
                    } else{
                        res.push(item[i])
                     }
            }
        }
        arr(num)

BFC

BFC的理解

块级格式化上下文,他是指一个独立的块级渲染区域,只有block-level BOX参与,该区域拥有一套渲染规则来约束盒子的布局,且与区域外部无关

从一个现象开始说起

一个盒子不设置height,当内容子元素都浮动时,无法撑起自身

该盒子没有形成BFC

如何创建BFC

方法一:float的值不是none

方法二:position的值不是static或者relative

方法三:display的值时inline-block,flex或者inline-flex

方法四:overflow:hidden

BFC的其它作用

BFC可以取消盒子margin塌陷

BFC可以组织元素被其它元素覆盖

reduce

arr.reduce(function(rpev,cur,index,arr){   ... })

​ arr表示原数组

​ prev表示上一次调用回调时的返回值,或者初始值 init

​ cur表示当前正在处理的数组元素

​ index表示当前正在处理的数组元素的索引,若提供init值,则索引为0,否则索引为1

​ init表示初始值

image.png 上图因没设初始值,所以,pre索引为0,值为1,cur索引为1,值为2

统计名字出现的次数

const person = ['zyf','zyf','ls','pp','pp']
const nameNum = person.reduce((pre,cur)=>{
    if(cur in pre){
        pre[cur]++
    }else{
        pre[cur] = 1
    }
    return pre
},{})
console.log(nameNum);	//{zyf: 2, ls: 1, pp: 2}

image.png 用reduce实现数组扁平化

const array = [1,2,3,[4,5,[6,7,8]]]
const newArr = (arr)=>{
    return arr.reduce((pre,cur)=>{
        return pre.concat(Array.isArray(cur) ? newArr(cur) : cur)
    },[])
}
console.log(newArr(array));
 <script>
        //构造函数继承
        function Parent(name){
            this.name = name
        }
        Parent.prototype.getName = function(){
            return this.name
        }
        //在子类的构造函数中 执行弗雷的构造函数 并且为其绑定子类的this
        function Child(){
            Parent.call(this, '蔡大大')
        }
        const child1 = new Child()
        const child2 = new Child()
        child1.name = '鹿晗'
        console.log(child1.name);
        console.log(child2.name);
        console.log(child2.getName());
        //并不能继承父类原型上的方法 和 属性
    </script>

寄生组合式继承

function Parent(name){
            this.name = name
}
Parent.prototype.getName = function(){
    return this.name
}
//在子类的构造函数中 执行弗雷的构造函数 并且为其绑定子类的this
function Child(){
    Parent.call(this, '蔡大大')
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
const child1 = new Child()
const parent = new Parent()
console.log(child1.getName())
console.log(parent.getName())

提前退出提前返回

不用提前退出提前返回,就会无限if循环

function print(animal){
            let result = null
            if(animal){
                if(animal.type){
                    if(animal.name){
                        if(animal.gender){
                            result = `${animal.name} is a ${animal.gender}`
                        }else{
                            result = 'no animal gender'
                        }
                    }else{
                        result = 'no animal name'
                    }
                }else{
                    result = 'no animal type'
                }
            }
        }
        console.log(print({type: 'dog', gerder:'female'}));

用了之后

const print = ({type, name, gender})=>{
            if(!type) return 'no animal type'
            if(!name) return 'no animal name'
            if(!gender) return 'no animal gender'
            return `${name} is a ${gender} ${type}` 
        }
console.log(print({type: 'dog', gender:'female'}));

switch语句替换

switch语句

function printFruits(color){
    switch(color){
        case 'red':
            return 'apple'
        case 'yellow':
            return 'bananas'
        default:
            return [] 
    }
}
console.log(printFruits('yellow'));

改变:

 const fruit = {
     red:'apple',
     yellow:'bananas',
     green:'watermelon'
 }
 console.log(fruit['red']);