js

2019-12-09  本文已影响0人  fanstastic
var a = (b = 2) => { console.log(b) }
a(undefined) // 2
a() // 2
a(null) // null

语法不能polyfill,但可以transpiling

模块

class

class Foo {
  constructor(a, b) {
    this.x = a
    this.b = b
  }
  gimmeXY() {
    return this.x * this.y
  }
}

随笔技术

同构,浏览器端会在执行一次,所以要进行一次判断,如果数据已经获取,那么就不要再获取数据。

在当前作用域之外执行的函数就是闭包,定义时确定作用域,运行时确定this,作用域链是基于调用栈的。

if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
        throw new TypeError('')
    }
  }
  let args = Array.prototype.slice.call(arguments, 1),
  fToBind = this, // this指向需要被绑定this的函数
  fNOP = function() {},
  fBound = function() {
    
  }
  
}

函数是对象的子类型,可以像使用对象一样使用函数,new 出来的实例可以通过instance判断是否是new 出来的实例

  1. 如果在prototype链上层存在foo,但是他被标记为只读,那么无法修改已有属性,或者创建屏蔽属性。只读会阻止链下层隐式创建同名属性。这个限制只会存在于=赋值中,使用Object.defineProperty并不会受到影响。
    a++,首先通过原型查找到a,然后再对象自身的属性上创建一个值,原型的值不会发生改变。
function Foo(who) {
  this.me = who
}
Foo.prototype.identify = function() {
  return 'i am' + this.me
}
function Bar(who) {
  Foo.call(this, who)
}
Bar.prototype = Object.create(Foo.prototype)
  1. 代理在先,代理在后
    我们通常可以把代理看作是对目标对象的包装。代理成为了代码交互的主要对象,而实际的目标对象保持被保护的状态。
  1. 首先,按照数字上升排序,枚举所有整数索引拥有的属性;
  2. 然后,按照创建顺序枚举其余的拥有的字符串属性名;
  3. 最后,按照创建顺序枚举拥有的符号属性;
function trampoline(res) {
  while(typeof res == 'function') {
    res = res()
  }
  return res
}

let foo = (() => {
  function _foo(acc, x) {
    if (x <= 1) return acc;
    return () => {
      return _foo((x/2)+acc, x-1)
    }
  }
  return (x) => {
    return trampoline(_foo(1, x))
  }
})()

这个重写需要最小的改动把递归转化为trampoline中的循环。

  1. 首先,把 return _foo .. 一行封装在·partial表达式中
  2. 然后,把_foo调用封装在trampoline中
function foo(x) {
  let acc = 1;
  while(x>1) {
    acc = (x/2)+acc
    x--
  }
  return acc
}
try {
  (function foo(x) {
    if (x < 5E5) return foo(x+1)
  })(1)
}
catch (err) {
  
}

在非TCO引擎中,递归循环最终会失败,抛出一个异常被捕获。
所以我们可以通过这种特性测试来决定是加载使用递归的应用代码版本,还是转换为不需要递归的版本。

自适应代码

function foo(x) {
  function _foo() {
    if (x > 1) {
      acc = acc + (x/2);
      x--
      return _foo()
    }
  }
  var acc=1;
  while(x>1) {
    try {_foo()} catch(err){}  
  }
  return acc
}
foo(123456)

这个算法尽可能多的使用了递归,但是是通过作用域内的变量x和acc保持进展状态。如果整个问题都可以不出错的通过递归解决,那么很好。如果引擎在某处杀死了递归,我们就会在catch中捕获到,然后再试一次,继续我们其余的工作。
这种形式可以看做一种元编程,理由是在运行时探索引擎的能力来递归地完成任务,并可能为引擎局限提供替代版本。

上一篇 下一篇

猜你喜欢

热点阅读