前端基础夯实

89 阅读4分钟
1 如何跳出forEach循环
 const ary = [1, 2, 3, 4, 5]
        // 场景1: 当值为3时,跳出整个循环,打印出1,2,(使用for)
        for (let i = 0, len = ary.length; i < len; i++) {
            const item = ary[i]
            if (item === 3) break
            console.log(item)
        }
        // 场景2: 当值为3时,跳出本次循环,打印出1,2,4,5,(使用for)
        for (let i = 0, len = ary.length; i < len; i++) {
            const item = ary[i]
            if (item === 3) continue
            console.log(item)
        }
        // 场景3: 当值为3时,跳出整个循环,打印出1,2(使用foreach)(tip: 抛出异常)
        try {
            ary.forEach(item => {
                if (item === 3) throw new Error('终止循环')
                console.log(item)
            })
        } catch(e) {
            console.log(e)
        }
        ary.every(item => {
            console.log(item)
            return item !== 2
        })
        // 场景4: 当值为3时,跳出本次循环,打印出1,2,4,5(使用foreach)
        ary.forEach(item => {
            if (item === 3) return false
            console.log(item)
        })
       ary.some(item => {
            if (item === 3) return false
            console.log(item)
        })
        /**
         * for 和 forEach的区别:
         * 1. forEach 不能使用break和continue; 但可以通过抛出异常的方式实现break的效果,通过return实现continue的效果
         * 2. forEach 本身无法跳出循环,必须遍历所有的数据才能数据
         * 3. for循环的性能比forEach快1倍,forEach比map快20%左右,因为for循环没有额外的函数调用栈和上下文,所以它的实现最简单;forEach中包含了参数和上下文,性能会降低;而map因为会返回一个新数组,数组的创建和赋值都需要分配内存空间,所以性能开销最大
         * 4. forEach 的优势:它传入一个函数,因此形成了一个作用域,它内部所定义的变量不会污染全局变量 
        */

2 如何判断对象中有没有某个属性
        const obj = {
            name: 'zhangsan'
        }
        // 1 in obj (如果指定属性在对象或其原型链上,则 in obj 返回true)
        console.log('name' in obj) // true
        console.log('toString' in obj) // true
        console.log('---分割线1----')
        // 2 Reflect.has 检查属性是否在对象中,它像 in Operate一样作为函数工作
        console.log(Reflect.has(obj, 'name')) // true 
        console.log(Reflect.has(obj, 'toString')) // true
        console.log('---分割线2----')
        // 3 hasOwnProperty(它可以正确区分对象本身的属性和其原型的属性)
        console.log(obj.hasOwnProperty('name')) // true
        console.log(obj.hasOwnProperty('toString')) // false
        console.log('---分割线3----') 
        // 4 Object.prototype.hasOwnProperty
        console.log(Object.prototype.hasOwnProperty.call(obj, 'name')) // true
        console.log(Object.prototype.hasOwnProperty.call(obj, 'toString')) // false
        console.log('---分割线4----')
        // 5 Object.hasOwn
        console.log(Object.hasOwn(obj, 'name')) // true
        console.log(Object.hasOwn(obj, 'toString')) // false
3 数据类型
基本数据类型:String/Number/Boolean/Null/Undefined/Symbol
引用数据类型:Object/Array/Function/RegExp/Date
4 判断数据类型的方法
//null 表示对空对象的引用,表示一个空对象指针,实际上是基础类型
// typeof 只能判断除null之外的基本数据类型:
       console.log(typeof '3') // 'string'
       console.log(typeof 3) // 'number'
       console.log(typeof true) // 'boolean'
       console.log(typeof null) // 'object' *
       console.log(typeof undefined) // 'undefined'
       console.log(typeof Symbol(1)) // 'symbol'
       console.log(typeof {a: 1}) // 'object'
       console.log(typeof [1]) // 'object' *
       console.log(typeof function(){}) // 'function'
       console.log(typeof new RegExp()) // 'object' *
       console.log(typeof new Date()) // 'object'*
// Object.prototype.toString
   console.log(Object.prototype.toString.call('aa')) //[object String]
   console.log(Object.prototype.toString.call(1)) // [object Number]
   console.log(Object.prototype.toString.call(false)) // [object Boolean]
   console.log(Object.prototype.toString.call(null))// [object Null]
   console.log(Object.prototype.toString.call(undefined))// [object Undefined]
   console.log(Object.prototype.toString.call(Symbol(1)))// [object Symbol]
   console.log(Object.prototype.toString.call({a:1}))// [object Object]
   console.log(Object.prototype.toString.call([1,2,3]))// [object Array]
   console.log(Object.prototype.toString.call(function(){}))// [object Function]
   console.log(Object.prototype.toString.call(new RegExp()))// [object RegExp]
   console.log(Object.prototype.toString.call(new Date()))// [object Date]
    // instanceof 用来检测某个实例对象的原型链上是否存在构造函数的prototype属性
       function Person(name) {
           this.name = name
       }
       const p = new Person('sunshine')
       console.log(p.name)
       console.log(p instanceof Person) // true
       console.log(p.__proto__ === Person.prototype) // true
       console.log(p.__proto__.__proto__ === Object.prototype) // true
       console.log('--------------')
       // 缺点: 实例是一个对象或函数创建的,是引用类型,所以无法检测基本类型的数据。
       //并且,所有引用类型的祖先都是Object对象
       const obj = {
           a: 1
       }
       const ary = [1, 2]
       const fn = function () {
           console.log('12212')
       }
       const reg = new RegExp()
       const d = new Date()
       console.log(obj instanceof Object)// true
       console.log(ary instanceof Array)// true
       console.log(fn instanceof Function)// true
       console.log(reg instanceof RegExp)// true
       console.log(d instanceof Date)// true
       console.log(d instanceof Object)// true
       console.log('--------------')
       console.log('1' instanceof String) // false
       console.log(1 instanceof Number)// false
       console.log(false instanceof Boolean)// false
       console.log(Symbol(1) instanceof Symbol)// false
       console.log(null instanceof Null)// 报错
       console.log(undefined instanceof Undefined) // 报错
// 总结: instanceof可以检测所有能转换为实例对象的数据;所有引用类型都是Object的实例
// 手写instancceof
    function myInstanceof(instanceObj, constructorFun) {
            // 获取构造函数的原型对象
            const prototypeObj = constructorFun.prototype
            // 获取实例对象的原型
            let instanceProto = instanceObj.__proto__
            // 向上查找原型链,直到null为止
            while (instanceProto) {
                if (prototypeObj === instanceProto) {
                    return true
                }
                console.log('zouni----')
                instanceProto = instanceProto.__proto__
            }
            console.log('zouni2------')
            return false
        }
        console.log(myInstanceof('', String))
        console.log(myInstanceof(1, String))

        function Person(name) {
            this.name = name
        }
        const p = new Person('sunshine')
        console.log(myInstanceof(p, Person))

 // constructor: 查看目标构造函数,进行数据类型判断,但不能判断null和undefined;
        const obj = {
            a: 1
        }
        const ary = [1, 2]
        const fn = function () {
            console.log('12212')
        }
        const reg = new RegExp()
        const d = new Date()
        console.log(obj.constructor === Object) // true
        console.log(ary.constructor === Array) // true
        console.log(ary.constructor === Object) // false
        console.log(fn.constructor === Function)// true
        console.log(reg.constructor === RegExp)// true
        console.log(d.constructor === Date)// true
        console.log('--------------')
        console.log('1'.constructor === String) // true
        console.log(1..constructor === Number)// true
        console.log(false.constructor === Boolean)// true
        console.log(Symbol(1).constructor === Symbol)// true
        console.log(null.constructor)// 报错
        console.log(undefined.constructor) // 报错

5 如何判断是不是数组
   //根据上面判断数据类型的方法可以得知:
   //1.Object.prototype.toString, 通过对象原型的方法判断
   Object.prototype.toString.call([]) === '[object Array]'
   //2.instanceOf, 判断是否属于数组实例
   [] instanceof Array // true
   //3.constructor
   [].constructor === Array // true
   4.Array.isArray
   Array.isArray([]) // true
6 字符串如何转数字

Number/*/+

Number(''); 1*'';+''// 0
Number('2a'); 1*'2a';+'2a'// NaN
Number(' 2 2');  1*'  2 22';+'2 2'// NaN

补充: Math.floor() 向下取整

Math.floor('1.9') // 1
Math.floor('1.9a') // NaN
Math.floor('') // 0
Math.floor('2 2') // NaN

parseInt、parseFloat

以下输出结果都为2
parseInt('2')
parseInt('2.9')
parseInt('2yea')
parseInt('2 7')

parseFloat("10");        // returns 10
parseFloat("10.33");     // returns 10.33
parseFloat("10 20 30");  // returns 10
parseFloat("10 years");  // returns 10
parseFloat("years 10");  // returns NaN
7 NaN
NaN === NaN // false
isNaN(NaN) // true
8 补充
        function isHtmlElement(node) {
            return node && node.nodeType === Node.ELEMENT_NODE
        }
        const bodyNode = document.getElementsByTagName('body')[0]
        console.log(isHtmlElement(bodyNode)) // true
    const isFunction = (fn) => {
        const getType = {}
        return fn && getType.toString.call(fn) === '[object Function]'
    }
    console.log(isFunction(() => {}))
        
 const isUndefined = (val) => {
            return val === void 0;
        }
        const isDefined = (val) => {
            return val !== undefined && val !== null
        }
        var a;
        console.log(isUndefined(a))   // true     
        console.log(isDefined(a)) // false