2022年1月

看到一篇不错的国外整理文章,特此记录下. 使用原生js监控变量的变化主要有6种,具体如下.
  • 1.使用setInterval轮询检测

    <script>
      /**
       * 轮询检测变量变化
       * @param varName '要检测的变量名称'
       * @param callback '变量变化后执行的函数'
       * @param checkTimes '需要检测几次.0表示一直检测,1为检测1次就停止检测,以此类推'
       */
      function watch(varName, callback, checkTimes = 1) {
          clearcheck = setInterval(repeatcheck, 500, varName);//500毫秒检测一次
          let current = 0;
          let oldvalue = window[varName]
          function repeatcheck(varName) {
              if (window[varName] !== oldvalue) {
                  current++;
                  callback && callback(oldvalue, window[varName], current)
                  if (checkTimes > 0 && current > checkTimes) {
                      clearInterval(clearcheck);
                  }
                  console.log(`${varName} value changed from ${oldvalue} to ${window[varName]} (${current} times)`);
                  oldvalue = window[varName]
              }
          }
      }
      //用法
      var myVar = 'hello';//初始化要检测的变量,一定要声明为全局变量
      let title = 'beautiful!';
      watch('myVar', function (oldValue, newValue, changeTImes) {//changeTImes: 改变的次数
          //do something you want.做你的逻辑
          alert(`changeTime ${changeTImes}: ; now value is: ${newValue}`)
      }, 0)
      myVar = 'world';//改变值,测试下
    </script>
    
  • 2.监听DOM变化

    //设置隐藏的dom
    <div id="watchdiv" style='visibility:hidden;width:0;height:0'>0</div>
    <script>
    document.getElementById('watchdiv')
        .addEventListener('DOMSubtreeModified', function () {
            //做你的逻辑
            console.log("value changed to "
                + document.getElementById('watchdiv').innerHTML)
        });
    </script>
  • 3.为对象的每个属性设置setter和getter

    缺点就是需要较多的设置代码; 同时对于新增或删除的属性是通知不到的.为属性设置setter和getter官方文档
    看下这个简单栗子,很容易就会用了.
      const o = {
     a: 7,
     get b() {
         return this.a + 1;
     },
     set c(x) {
         this.a = x / 2;
     }
      };
      console.log(o.a); // 7
      console.log(o.b); // 8 <-- 这时get b()会被调用
      o.c = 50;         //   <-- 这时set c(x)会被调用
      console.log(o.a); // 25
  • 4.使用代理对象proxy object (都2202年了推荐使用这个)

    proxy object方法简单说就是他能为一个目标对象创建一个代理对象,所有操作都会被代理对象拦截下来且可被重新定义操作.(我们操作代理对象而不是直接操作目标对象).举个简单栗子很快就会明白.
      let targetObj = {};
      let targetProxy = new Proxy(targetObj, {
     set: function (target, key, value) {//设置对象属性会被调用
         //做你的逻辑
         console.log(`${key} set to ${value}`);
         target[key] = value;
         return true;
     },
     get: function (target, key) {//访问对象属性会调用
         //做你的逻辑
         console.log(`access the ${key}`)
     }
      });
      targetProxy.a = 'test'//注意是操作代理对象,而不是直接操作目标对象

    更多高级详尽proxy介绍看官方文档

综上,第3和4方法会比较好用,其中推荐可采用第4种方法.


参考:
https://stackoverflow.com/questions/1759987/listening-for-variable-changes-in-javascript
https://lage.us/Javascript-Watch-Variables-for-Change.html

有时候我们需要访问变量名动态指定的变量.
js中有两种方法可以做到.
  • js有万物皆对象和上下文的概念.当你声明一个全局变量,他会存在window变量中,所以你直接用window[变量名]或者window.变量名的方式即可访问到.
  • 使用是eval()函数解析;不过会存在安全问题,你必需清楚你传入的变量.此外如果是在函数中使用,eval会先在函数内部找,然后一层一层向上找变量,而不是像window那样只能取全局的.

下面举个栗子:

varName = 'a'
var a = 'hello world'; //注意用let和const声明的是局部变量,所以全局window中是不存在该变量的.var可写可不写,不写默认也是var声明方式.
function test(){
   let a = 'good';
   eval(varName); //eval()能先找最近范围内变量,输出 good
   window[varName]; //输出 hello world
}
test()

phpstorm提供了html,php文件可直接在phpstorm中预览结果或者在浏览器打开该文件预览结果.这个按钮就在文件的右上角,可以很方便打开预览.其实原理就是,phpstorm会开启个内建的服务,当你预览文件时,它就访问localhost:port/你的项目目录名称/文件的具体路径.文件后缀

不过最近发现打开报错404 not found.看了下打开的链接, 发现路径不对,多了一层项目.知道原因就解决一半了.问题大概就是项目的根路径没设置对.订正配置项目根路径方法如下:

  1. 打开配置: phpstorm -> preferences
  2. 点开 Directories 选项
  3. 在右边看下 add content root块下项目是否设置正确,不对订正他;为空点+新增一个.
  4. 最后别忘了点击ok使更改生效.

找个文件,点击文件右上的build-in preview图标,验证下是否能成功预览.(提示:预览php文件,需要配置下本地php解释器).

出现这个错误,是因为一个带有protected或private的constructor无法被初始化. 每次实例化时,constructor都会被调用. 所以当你新建对象时$obj = new myObj();会报错.只有constructor为public级别才能被初始化.
通常,protected或private应用在单例中,避免被直接初始化.一般class中会有类似getInstance()方法来获取实例.

go安装依赖时,提示下载超时.有点经验的应该也能猜到应该就是需要科学上网才行.知道原因后,思路就很明了.使用代理.
shell中GOPROXY环境可以控制go使用的代理.
解决方案一:(使用第三方镜像,这家好像不错https://goproxy.io/zh/)
export GOPROXY=https://goproxy.io,direct
方案二:(如果你本地电脑可以科学上网,走科学上学的网络)
export GOPROXY=https://127.0.0.1:10086,direct