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