D3.js Essential Notes

  1. Definition
    1. D3 stands for Data-Driven Document
    2. D3.js is a JavaScript library for easing data visualization
    3. Important Notes about D3.js:
      • D3.js ver. 4 and ver. 3 are incompatible
      • D3.js is a large lib, with ver. 4.10.2 sizing about 213 KB
      • D3.js ver. 4 is modular
      • Open Source Examples: bl.ocks.org
  2. D3.js with SVG
    1. Essential Shapes
      let dataToVisualize = [1, 2, 3]
      
      // creating the SVG element
      let svg = d3.select("body").append("svg")
        .attr("height", 300).attr("width", "300")
      
      // visualizing the data
      svg.selectAll("rect")
       .data(dataToVisualize)
       .enter().append("rect")
         .attr("height", function(d, i){ return d*100 })
         .attr("width", "50")
         .attr("fill", "red")
         .attr("x", function(d,i){ return i*60 })
         .attr("y", function(d,i){ return 300-(d*100) })
      // Tricks: 
      // (1) overlaying shapes driven by the same data
      // (2) use a template (bl.ocks.org)
    2. Generators
      • d3.line()
        let dataToVisulize = [10, 30, 20, 40, 50, 30]
        let svg = d3.select("body").append("svg")
         .attr("height", "200px").attr("width", "360px")
        
        let lineGen = d3.line()
          .x(function(d,i){ return i*60 })
          .y(function(d,i){ return d*4 })
          // try them for fun
          // .curve(d3.curveStep)
          // .curve(d3.curveCardinal)
        svg.append("path")
          .attr("fill", "none")
          .attr("stroke", "red")
          .attr("d", lineGen(dataToVisulize))

BOM APIs: deviceproximity & userproximity

// 挺好玩的,就是想不到怎么利用这些数据,
// 或许给小孩子表 演一个魔术?
// 不同设备采样的传感器位置不一,
// 多数在(主)屏幕一面
window.addEventListener("deviceproximity", function(e){
  // your imagination ... 
  document.body.innerHTML = `
  DeviceProximityEvent.max: ${e.max}
  DeviceProximityEvent.min: ${e.min}
  DeviceProximityEvent.value: ${e.value}
  `
})
// 同上
window.addEventListener("userproximity", function(e){
  // your imagination ...
  if(e.near){
    alert("fun fact:手机屏幕上有很多细菌")
  }
})

类似的API还有:DeviceMotionEvent

BOM APIs: window.DeviceLightEvent

// 网页应用可以根据(手机)用户当前的环境光亮度,
// 来相应地执行一些任务。
// 比如,根据如果用户所在环境光线比较暗,将网页切换至夜间模式
if(window.DeviceLightEvent){
  window.addEventListener("devicelight", function(aDeviceLightEvent){
    let currentAmbientLightInLux = aDeviceLightEvent.value
    // your imagination ... 
  })
}else{
  // API Not Available
}
window.addEventListener("devicelight", function(aDeviceLightEvent){
  let currentAmbientLightInLux = aDeviceLightEvent.value
  // your imagination ... 
})
window.ondevicelight = function(aDeviceLightEvent){
  let currentAmbientLightInLux = aDeviceLightEvent.value
}

BOM APIs: navigator.getBattery()

if (navigator.battery 
 || navigator.webkitBattery 
 || navigator.mozBattery 
 || navigator.msBattery) {
  // 老API
}else if(navigator.getBattery()){
  navigator.getBattery().then(function(bat){
    // 新API
    console.log(bat)
  })
}else{
  // 无API
}

一份有趣的JavsScript (ECMAScript 3rd Edition)题目

个人认为,很多JavaScript(面试)题与程序员解决现实问题的能力的关系不大。但是,如果你以编程为乐的话,做题挺好玩的。

原题在这里。下面所有题目的问题都是:“下面的程序的运行结果是?”

  1. 关键词arguements
    (function(){ 
      return typeof arguments // "object"
    })();
  2. 变量声明
    var f = function g(){ return 23; };
    typeof g(); // err, g not defined
  3. 原始数据
    console.log( (function(x){
      delete x;
      return x;
    })(1) ); // 1
    // 原始数据delete不了
  4. 变量声明
    var y = 1, x = y = typeof x;
    console.log(x); // "undefined"
    // 第一行做了这些事情
    // 1)声明了变量y
    // 2)给变量y赋值1
    // 3)声明了变量x
    // 4)给变量x赋值前就使用“typeof x”,“typeof x”返回字串"undefined"
    // 5)把变量x以及变量y赋值为“tyoeof x”,也就是字串"undefined"
  5. 把函数传入函数
    (function f(f){
      return typeof f(); // "number"
    })( function(){return 1;} );
  6. this的指向
     var foo = {
       bar: function() { return this.baz; },
       baz: 1
     };
     (function(){
       return typeof arguments[0]();  // "undefined"
     })(foo.bar);
    // this指向当前对象,arguments
  7. this的指向
    var foo = {
      bar: function(){ return this.baz; },
      baz: 1
    }
    typeof (f = foo.bar)(); // "undefined"
    // f被匿名执行,this指向Window
  8. IIFE
    var f = (function f(){ return "1"; }, function g(){ return 2; })();
    typeof f; // "number"
    // 两个并行的IIFE,总体返回值为取最后一个函数的返回
  9. 函数的提升与类的强制转换
    var x = 1;
    if (function f(){}) {
      x += typeof f;
    }
    x; // "1undefined"
    // 在if语句的条件中,通过function声明的变量与通过var声明的变量
    // 它们提升的行为不一。f
    // Function声明的变量不会称为全局
    // Function声明的变量甚至不可以被if语句内的程序所调用
    // 因此,typeof f的结果是"undefined"
    // 数字 + 字串,结果等同于:字串化的数字+字串
  10. typeof
    var x = [typeof x, typeof y][1];
    typeof typeof x; // "string"
    // 第一行代码等同于:" var x = typeof y; "
    // tyoeof返回值类型为字串
  11. 对象的写法
    (function(foo){
      return typeof foo.bar; // "undefined"
    })({ foo: { bar: 1 } });
  12. 函数的提升
    (function f(){
      function f(){ return 1; }
      return f();                    // 2
      function f(){ return 2; }
    })();
  13. 构造函数
    function f(){ return f; }
    new f() instanceof f; // false
  14. with
    with (function(x, undefined){}) length; // 2
    // with我不懂

JavaScript / ECMAScript工具

  1. 代码试验场(Code Playground)
    1. 通用:
      • 在线:CodePen || JSFiddle
      • 本地:Chrome > Dev Tools > Sources > Snippets
      • 本地:Chrome > Dev Tools > Console
      • 本地:$ node
    2. <canvas>:arbiter-frame
  2. Docs
    1. 原生JS:
    2. 原生JS超集:
    3. 浏览器相关
    4. 专项速查
  3. 教程
    1. ECMAScript 6入门 by 阮一峰
    2. es6-cheatsheet by DrkSephy
  4.  测试
    1. 付费:
    2. 漏洞检测:

前端跨域数据交换的常见方案摘要

  1. JSONP
    // 用户访问域名A,域名A下有.js文件包含以下代码
    let jsonpDemo = function(data){
      console.log(data.id === 1)
    }
    // 用户下域名B的.js文件(这样可以规避同源策略),并运行它
    jsonpDemo({"id": 1, "name": evan}) // true
  2. document.domain + iframe(仅适用于主域相同,子域不同的情景)
    // main domain page, say "main.com/index.html"
    <iframe src="https://sub.main.com/iframe.html"></iframe>
    <script>
      document.domain = "main.com"
      let data = "hello world"
    </script>
    // sub domain page, AKA, "sub.main.com/iframe.html"
    <script>
      document.domain = "main.com"
      console.log(window.parent.data) // hello world
    </script>
  3. location.hash + iframe:略
  4. window.name + iframe:略
  5. postMessage API
    数据的传输发生在本地。

    foo.com/foo.html
    <iframe id="iframe" src="http://www.bar.com/bar.html" style="display: none"></iframe>
    
    <script>
      let iframe = document.querySelector("#iframe")
      iframe.onload = function(){
        let data = { "id": 1, "msg": "Hello World" }
        // foo.com向bar.com传输数据
        // 部分浏览器只支持string类数据,因此将对象stringify一下
        iframe.contentWindow.postMessage(JSON.stringify(data)
        , "http://www.bar.com")
      }
      // 监听来自bar.com的数据
      window.addEventListener("message", function(e){
        alert(`data from bar.com: ${e.data}`)
      })
    </script>
    // bar.com/bar.html
    <script>
      window.addEventListener("message", function(e){
        let receivedData = JSON.parse(e.data)
        if(receivedData.msg === "Hello World"){
          window.parent.postMessage("Hello To You Too", "http://www.foo.com")
        }
      })
    </script>
  6. CORS || nginx代理 || Node.js中间件
    // 前端的原生ajax请求一般需要开启带cookies
    let ajax = new XMLHttpRequest()
    ajax.withCredentials = true
    
    // 其他的是后端的事情了
  7. Socket.io(WebSocket API):略
    WebSocket的其他fallbacks:Adobe Flash Socket、ActiveX HTMLFile (IE)
  8. 非跨域通讯:SharedWorker

via 前端常见跨域解决方案(全)

JavaScript Performance Tips

  1. Promote
    1. objects re-usage
    2. C style loops
    3. Thinking in device pixels. If the idea output image doesn’t fit, the browser will try to imitate it, which use lot of computing resources
  2. Avoid
    1. object allocation
    2. closures
    3. polymorphism
    4. duplicate code
    5. Using huge .gif format file and use .mp4 instead
    6. random (SVG/Canvas) stroke line art
  3. Code this way
    1. when animating an element, make it “position: absolute” to avoid recalculation of other elements’ positions. Also, try not to animate the width and height, which hogs CPU
  4. Use these tools
    1. Timeline of Chrome Dev Tools (most important)