【问题标题】:How to customize an inbuilt javascript function? [duplicate]如何自定义内置的 javascript 函数? [复制]
【发布时间】:2020-12-23 19:47:07
【问题描述】:

如何在 JavaScript 中自定义 console.log() 函数以保留其现有行为并添加自定义功能?

例如:此按钮在控制台中打印消息,这是它的预期行为

<html>

<body>

  <h1>Button Element</h1>
  <button type="button" id="some-btn" onclick="console.log('Message')">Click Me</button>

</body>

</html>

但我想向console.log() 添加自定义功能,同时仍然能够将消息打印到控制台。

console.log = (arg) => {
  document.getElementById("some-btn").innerHTML = arg
}
<html>

    <body>

      <h1>Button Element</h1>
      <button type="button" id="some-btn" onclick="console.log('Message')">Click Me</button>

    </body>

    </html>

在上面的 sn-p 中,我有 console.log() 函数所需的自定义行为,但它失去了在控制台中打印消息的原始功能。

如何同时保留旧功能和新功能?

【问题讨论】:

  • const { log: oldLog } = console; console.log = (...args) =&gt; { oldLog(...args); /* do your fancy stuff*/}
  • 但也 - 不要这样做 ;) 只需声明一个普通函数 function log() {} 即可满足您的需求,也可以满足 console.log
  • 这能回答你的问题吗? How to override a JavaScript function
  • 请花点时间阅读我的答案,我可能在那里花了太多时间。至少告诉我你的想法

标签: javascript function ecmascript-6


【解决方案1】:

您可以覆盖log 函数。但我不会推荐它:

const log = console.log;
console.log = (...args) => {
  log(...args);
  // your logic
}

做这样的事情:

const yourLog = (...args) => {
  console.log(...args);
  // your logic
}

你不应该覆盖内置函数等。

【讨论】:

  • 我同意,但这不属于意见范围吗?也许你可以用具体的理由来支持你的论点。
【解决方案2】:

所以,这就是我所做的,一个完整的解决方案,带有代码使用示例。

基本思想是保留console.log 上的引用,然后如问题所示重做其分配。

看起来像这样:

var consoleLogModus = 'original' // or 'custom'
var nativConsoleLog = console.log

console.log = (...args) =>
  {
  if (consoleLogModus === 'original' )
    {
    nativConsoleLog(...args)
    }
  else
    {
    //  your custom code for (console.log)
    }
  }

但是由于这给出了一个不太干净的代码,我更喜欢将它全部放在一个 IIFE 闭包中,并使用一个对象/方法来控制它。

如果我们想回到原来的 console.log 而不是将 console.log 放回其初始引用,我在其执行中使用了一个开关

结果就在那里,有一个完整的界面来测试它。

const consoleLogCommand = (function() // IIFE for control over console.log()
  {
  var nativConsoleLog = console.log
    , modusArr        = [ 'original', 'prefix', 'function' ]
    , prefix          = '>'        // default message
    , choose_modus    = modusArr[1] // default choice
    , redirect_fct    = () => {}    // default function
    , obj = 
      { setModus : modus =>
          {
          let n           = parseInt(modus) 
          if (isNaN(n)) n = modusArr.indexOf(modus)
          choose_modus    = modusArr[((n<0) ? 1 : n % 3)]
          }
      , getModus  : ()  => ({ lib:choose_modus, ref: modusArr.indexOf(choose_modus) })
      , setPrefix : inL => { let p = String(inL).trim(); prefix = (p.length) ? p : '>' }
      , getPrefix : ()  => prefix
      , redirect  : fct => { redirect_fct = fct }
      }
    ;
  window['console']['log'] = function(...args) // The new " console.log "
    {
    switch (choose_modus)
      {
      case modusArr[0]:               // 'natural':
        nativConsoleLog(...args)
        break;
      case modusArr[1]:               // 'prefix':
        console.clear()
        nativConsoleLog(prefix, ...args)
        break;
      case modusArr[2]:               // 'function':
        redirect_fct(...args)
        break;
      }
    }
  return obj
  } )()


/*------------------
  Test Interface :
-------------------*/

const myForm = document.forms['my-form'];
  
/* sample function 1 to replace console.log() */
function fct_one(...args) 
  {
  myForm['bt-4-fct1'].textContent = args.join('_')
  }

/* sample function 2 to replace console.log() */
function fct_two(...args) 
  {
  myForm['txt-4-fct2'].textContent = args.join('\n')
  }

/* summary of the possible functions for using the form interface */
const chooseFunction =
  { 'fct_one': fct_one
  , 'fct_two': fct_two
  }


const setRadioDefault = (rName, val) =>
  {
  myForm.querySelectorAll(`input[name="${rName}"]`).forEach(r=>
    {
    if (r.value === val) r.setAttribute('checked','checked')
    else                 r.removeAttribute('checked')
    })
  }
/* init...    */

  consoleLogCommand.setModus( 1 )
  setRadioDefault('modus', '1' )
  consoleLogCommand.redirect(fct_one)
  setRadioDefault('fct2Call', 'fct_one' )
  myForm.prefix.defaultValue   = consoleLogCommand.getPrefix()
myForm.reset()

myForm.oninput = e =>
  {
  switch(e.target.name)
    {
    case 'modus':    
        consoleLogCommand.setModus( myForm.modus.value )
        setRadioDefault('modus', myForm.modus.value )
        break;
    case 'prefix':   
        consoleLogCommand.setPrefix( myForm.prefix.value )
        myForm.prefix.defaultValue = consoleLogCommand.getPrefix()
        break;
    case 'fct2Call': 
        consoleLogCommand.redirect( chooseFunction[myForm.fct2Call.value] )
        setRadioDefault('fct2Call', myForm.fct2Call.value )
        break;
    }
  }
myForm.onsubmit = e =>
  {
  e.preventDefault()
  let args = [...myForm.arg].map(el=>el.value.trim()).filter(t=>t.length)
  console.log( ...args ) // finally
  }
.as-console-wrapper { max-height:100% !important; top:0; left:70% !important; width:30%; }
.as-console-row         { background-color: yellow; }
.as-console-row::after  { display:none !important; }
.as-console-row::before { content: 'log:'; font-size: .8em; }

body, textarea, input  {
  font-family : Helvetica, Arial sans-serif;
  font-size   : 14px;
  }
form {
  margin : 1em; 
  }
fieldset {
  width         : 40em;
  margin-bottom : .7em;
  border-radius : .6em;
  border-color  : turquoise;
  }
legend {
  padding      : 0 .5em;
  color        : darkblue;
  font-variant : small-caps;
  }
button {
  margin-left : 1.2em;
  }
label {
  display : inline-block;
  margin  : .7em 0 0 1.2em;
  }
textarea {
  vertical-align : top;
  margin-left    : .4em;
  padding        : .2em .4em;
  }
<form name="my-form">
  <h3> console.log Customazing ! </h3>
  <fieldset>
    <legend>Chose Mode : </legend>
    <label><input type="radio" name="modus" value="0"> original way  </label>
    <label><input type="radio" name="modus" value="1"> with prefix   </label>
    <label><input type="radio" name="modus" value="2"> call function </label>
  </fieldset>
  <fieldset>
    <legend>Parameters : </legend>
    <label> add Prefix : <input type="text" name="prefix" value="abc" placeholder="blah blah blah"> </label>
    <br>
    <label><input type="radio" name="fct2Call" value="fct_one"> call function 1 </label>
    <label><input type="radio" name="fct2Call" value="fct_two"> call function 2 </label>
  </fieldset>
  <fieldset>
    <legend> Arguments : </legend>
    <label> arg 1  : <input type="text" name="arg" value="" placeholder="console.log( arg1 )" > </label>
    <br>
    <label> arg 2  : <input type="text" name="arg" value="" placeholder="console.log( . , arg2 )" > </label>
    <br>
    <label> arg 3  : <input type="text" name="arg" value="" placeholder="console.log( . , . , arg3 )" > </label>
  </fieldset>
  <fieldset>
    <legend>Test Part : </legend>
    <label> function 1 = change this text button  : <button type="button" name="bt-4-fct1">text</button> </label>
    <br>
    <label> function 2 = change this text  : <textarea name="txt-4-fct2" placeholder="textarea"></textarea> </label>
  </fieldset>
  <button type="reset">reset console.log Arguments</button>
  <button type="submit">submit a console.log() </button>
</form>
 

【讨论】:

  • 什么是“CCL”?
  • @Bergi 一个疏忽,我使用大写字母替换我不想自动翻译的单词。然后我用正确的术语替换。
猜你喜欢
  • 1970-01-01
  • 2019-10-09
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
相关资源
最近更新 更多