Js 笔记

Posted by ONE on April 15, 2018

ECMAScript6学习笔记

  1. let and var

    • 两者都用来声明变量,let声明的变量,尽在代码作用域内有效。所以使用for循环时用let简单方便。
    • 涉及闭包的一个例子,使用let时,由于声明变量尽在代码作用块内有效,所以不会用let声明时不会出现因为引用导致的赋值错误情况。“一个闭包不能实现,就用两个闭包”。如下

    • function ninja() { 
        for (let i = 0; i < 10; i++) { 
      	  a[i] = function() { console.log(i); }; 
        }
      } 
      
    • 暂时性死区:let是无法先使用再声明的。
  2. 块级作用域

    • 函数可在块级作用域内声明。
    • do表达式:使块级作用域可以返回值
  3. const命令

    • 声明不可改变的常量,必须立即初始化。
    • 存在暂时性死区。
    • 本质是指向变量的内存地址不可改变。当遇到数组或对象时,指向的是首地址,所以可以改变数组和对象里的内容,但不可改变其指向另一个。。
    • 如果真不想给对象添加属性,将对象冻结-》Object.freeze方法。
  4. 顶层对象和全局对象

    • let、const、class声明的全局对象,和顶层对象是分开的
    • System.global在各种环境中都可以取到顶层对象。
    • import getGlobal from 'system.global'; const global =getGlobal();

Using Function

Anonymous function:

  • Reference losing:
var ninja = {
  show: function() { console.log("class it"); }
}

var samurai = {
  show: ninja.show;
}

ninja = {};
try {
  assert(samurai.show(), "Is this going to work?");
}

catch(e) {
  assert(false, "Uh, this isn't good!");
}
  • To solve the problem of reference losing, a inline function is used.

  • Function as object

    • Memorizing

      function isPrime(value) {
        if (!isprime.answers) isPrime.answers = {};
        if (isprime.answers[value] != null) {
          return isPrime.answers[value];
        }
        var prime = value != 1;
        for (var i = 2; i < value; i++) {
          if (value % i == 0) {
            isPrime.answers[value] = false;
            break;
          }
        }
        return isPrime.answers[value] = prime;
      }
      
  • Use call/apply method to cheat the function so that creat a efficient way to use other methods. Like this:

    Array.prototype.push.call(arg);
    // arg is not a array. But in this way it acts like an array;
    method.apply();
    Array.prototype.slice.call(arg, 1);
    
  • Override function

    • addMethod()

      addMethod(ninjas, "find", function() { return this.values; });
      
      addMethod(ninjas, "find", function() {
        var net = [];
        for (var i = 0; i < this.values.length; i++) {
          if (this.values[i].indexOf(name == 0)
            net.push(this.values[i]);
        }
        return net;
      });
      
      addMethod(ninjas, "find", function() {
         var net = [];
         for (var i =0; i < this.values.length; i++) {
           if (this.values[i] == (first + " " + last))
             ret.push(this.values[i]);
         }
         return net;
      })
      
  • 函数判断

  • A common way (can used in IE)

    function isFunction(fn) {
      return Object.prototype.toString.call(fn) === "[object Function]";
    }
    

Closure

  • bind : 绑定上下文

    Function.prototype.bind = function() {
      var fn = this,
      args = Array.prototype.slice.call(arguments),
      object = args.shift();
      return function() {
    	return fn.apply(object, args.concat(Array.prototype.slice.call(arguments)));
      };
    };
    
    var myObject = {};
    
    function myFunction() {
      return this == myObejct;
    }
    
    assert( !myFunction(), "Context is not set yet");
    var aFunction = myFunction.bind(myObject);
    assert( aFunction(), "Context is set properly");
    // In chrome, assert is used by console.assert;
    
  • 偏应用函数: Currying: 有预处理参数的函数

    Function.prototype.curry = function() {
      var fn = this;
      args = Array.prototype.slice.call(arguments);
      return function() {
        return fn.apply(this, args.concat( Array.prototype.slice.call(arguments)));
      }
    }
    Function.prototype.partial = function() {
      var fn = this, args = Array.prototype.slice.call(arguments);
      return function() {
        var arg = 0;
        for (var i = 0; i < args.length && arg < arguments.length; i++) {
           if (args[i] === undefined) {
             args[i] = arguments[arg++];
           }
        }
        return fn.apply(this, args);
      };
    };
    
  • Memorzing (Closure)

    Function.prototype.memoized = function(key) {
      this.values = this.values || {};
      return this._values[key] !== undefined ? this._values[key] : this._values[key] = this.apply(this, arguments);
    };
    
    Function.prototype.memorize = function() {
      var fn = this;
      return function() {
          return fn.memorized.apply( fn, arguments);
      };
    };
    
    var isPrime = (function(num) {
      var prime = num != 1;
      for (var i = 2; i < num; i++) {
          if (num % i == 0) {
              prime = false;
              break;
          }
      }
      return prime;
    }).memorize(); 
    
  • 包里的变量引用问题

function ninja() {
  var divs = $("div");
  for (var i = 0; i < 10; i++) {
    divs[i].addEventListener("click", functon() { alert("divs #" + i + " was clicked.")}, false);
  }
}
// As a result, i will always be 10;

// Use like this:

function ninja() {
  var divs = $("div");
  for (var i = 0; i < 10; i++) (function(n) {
    div[n].addEventListener("click", function() alert("div #" + n + " was clicked."); }, false); })(i);
}