自定义方法替代控制台输出console.log()

本文深入探讨了在JavaScript中封装console.log()函数的原因和方法,解释了如何利用apply()函数来处理不定数量的参数,避免生产环境中因遗留debug语句而导致的信息泄露。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面试中遇到过的一道面试题:如何封装一个console.log()?
当时实在不理解为什么要封装这个,为什么不直接拿来用,可能是为了考察applyarguments
回来之后问了度娘,得到了部分的答案:

在开发的过程中,可能会因为debug,加入console.log()这样的语句,在控制台输出内容,方便debug,但是往往上生产就忘记删除,导致信息泄露...

当然,它的功能可能不仅仅于此,还有其他功能待挖掘,今后再做补充吧。
仅仅是封装这个功能很简单,用到了apply()

function logInfo(){
  console.log.apply(console,arguments);
}

就可以直接拿来用了,为什么要使apply再指向console呢?
是因为我们其实还是要使用console.log()这个方法来做输出,只不过每次输出的内容不一样,这里的内容就是arguments
很明显在这个封装的方法中传入的参数是不确定的,并不确定你要在控制台输出什么东西,所以传入的参数就无法预知,这也就是call(单个字符串)apply(数组)的区别,所以这个时候就要用到arguments对象了,官方的说法:

arguments 是一个对应于传递给函数的参数的类数组对象。
arguments对象不是一个 Array 。它类似于Array,但除了length属性和索引元素之外没有任何Array属性。

arguments在封装的方法中,是作为一个实参传递给了log()方法,例如:logInfo('hello','world'),那么arguments就是['hello','world'],使用console.log.apply(console,arguments)主要是用来把arguments中的每个参数都作为实参来传递给console.log()的。
如果像下面这样直接调用:

function logInfo() {
  console.log(arguments);
}
logInfo(1, 2, 3); // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]

那么会将arguments作为一个数组进行打印输出,而不是将其中的每一项作为参数传递给console.log()进行输出,很明显,上例的结果并不是我们想要的,我们想要的结果是这样的1,2 3,而apply()就正好可以实现这个需求。
回顾下apply()的知识:

  • 语法func.apply(thisArg,[argsArray])
  • thisArg
    在 func 函数运行时使用的 this 值。
  • argsArray
    一个数组或者类数组对象,其中的数组元素将作为单独的参数传给func函数
    这也就是为什么apply()能实现这个需求的原因,
  • 它会将数组(即封装函数中的arguments)中的每个元素都作为参数传递给函数(也就是console.log())。
7.1.10、迭代器遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费,原生具备 iterator 接口的数据:ArrayArgumentsSetMapStringTypedArrayNodeList注意:需要自定义遍历数据的时候,要想到迭代器工作原理:创建一个指针对象,指向当前数据结构的起始位置第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员每调用 next 方法返回一个包含 value 和 done 属性的对象案例演示:遍历数组//声明一个数组const xiyou = ["唐僧", "孙悟空", "猪八戒", "沙僧"];//使用 for...of 遍历数组for (let v of xiyou) { console.log(v);}console.log("===============");//获取迭代器对象let iterator = xiyou[Symbol.iterator]();//调用对象的next方法console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());12345678910111213141516案例演示:自定义遍历数据//声明一个对象const banji = { name: "五班", stus: [ "张三", "李四", "王五", "小六" ], [Symbol.iterator]() { //索引变量 let index = 0; let _this = this; return { next: function () { if (index < _this.stus.length) { const result = {value: _this.stus[index], done: false}; //下标自增 index++; //返回结果 return result; } else { return {value: undefined, done: true}; } } }; }}//遍历这个对象for (let v of banji) { console.log(v);}1234567891011121314151617181920212223242526272829303132337.1.11、生成器生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。7.1.11.1、生成器函数使用代码说明:* 的位置没有限制生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码next 方法可以传递实参,作为 yield 语句的返回值function * gen() { /*代码1开始执行*/ console.log("代码1执行了"); yield "一只没有耳朵"; /*代码2开始执行*/ console.log("代码2执行了"); yield "一只没有尾巴"; /*代码3开始执行*/ console.log("代码3执行了"); return "真奇怪";}let iterator = gen();console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log("===============");//遍历for (let v of gen()) { console.log(v);}123456789101112131415161718192021227.1.11.2、生成器函数参数function * gen(arg) { console.log(arg); let one = yield 111; console.log(one); let two = yield 222; console.log(two); let three = yield 333; console.log(three);}//执行获取迭代器对象let iterator = gen('AAA');console.log(iterator.next());//next方法可以传入实参console.log(iterator.next('BBB'));console.log(iterator.next('CCC'));console.log(iterator.next('DDD'));1234567891011121314151617187.1.11.3、生成器函数实例案例演示:1s后控制台输出 111,2s后输出 222,3s后输出 333function one() { setTimeout(() => { console.log(111); iterator.next(); }, 1000)}function two() { setTimeout(() => { console.log(222); iterator.next(); }, 2000)}function three() { setTimeout(() => { console.log(333); iterator.next(); }, 3000)}function * gen() { yield one(); yield two(); yield three();}//调用生成器函数let iterator = gen();iterator.next();123456789101112131415161718192021222324252627282930案例演示:模拟获取 ,用户数据 ,订单数据 ,商品数据function getUsers() { setTimeout(() => { let data = "用户数据"; iterator.next(data); }, 1000);}function getOrders() { setTimeout(() => { let data = "订单数据"; iterator.next(data); }, 1000);}function getGoods() { setTimeout(() => { let data = "商品数据"; iterator.next(data); }, 1000);}function * gen() { let users = yield getUsers(); console.log(users); let orders = yield getOrders(); console.log(orders); let goods = yield getGoods(); console.log(goods);}//调用生成器函数let iterator = gen();iterator.next();123456789101112131415161718192021222324252627282930313233
最新发布
04-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值