program javascript application 看了这个书, 才知道我对js对象一无所知. 感谢Eric Elliott大神. 大神为了写书, 至少弄了3个样例框架. 未来的spring啊.

构造函数 竟然是不该使用的方法

虽然我也讨厌new, 可是真没想到竟然是这个结论, js使用构造函数, 就是跑偏了.

funciton car(){}
var mycar= new car; //就是这种写法不要搞.
字面量是王道, 然而有作用域问题
  • 这里其实我不是很理解, 难道不能用let规避吗?
var mycar={
	color: 'pink',
	gas: function gas(){
    return this; //为了链式调用, 所有方法都要return this.
  },
}
工厂方法
//正常的工厂
var car=function car(a, b, c){
  var xxx; //这里其实声明的是一个私有变量, 不能被外部直接访问.
  return{ a,b,c, 
         br:function br(){},
        }
}

//单例工厂
function fac(){
  var x={}; //这个就是单例对象, 私有且唯一.
  return {
    get: function get(){
      return x;
    }
  }
}
var h1=fac().get();
var h2=fac().get();
//现在h1和h2其实指向同一个对象.

工厂方法的进一步提升
var carproto={
  //...省略
},
car=funciton car (op){
  return extend(object.create(carProto),op);  //感觉这里或许可以直接用object.assign
},
mycar=car({a:'a'});

关于工厂有一个建议, 对象和数组这种引用类型的使用要注意一下, 直接新建比较好.

相关基础知识插入 extend和object.create

extend的underscore实现, 这个实现了原型克隆.

_.extend=function(ob){ //第一个参数是待处理的返回值.
	each(slice.call(arguments,1), function(source){ //把后面的每一个参数都处理为第一个参数的属性.
		for(var pr in source){
			ob[pr] =source[pr];
		}
	});
	return ob;
};

object.create, 这个实现了原型代理

Object.create(proto, [propertiesObject])
//可以这么实现:
Object.create=function(o){
  function f(){};
  f.prototype=o;
  return new f;
}

共享原型模式

var carproto={
  //...省略
},
car=funciton car (){
  return object.create(carProto);  //
},
mycar=car(); 
youcar=car(); //这些都是用了同样的原型.
作者自己的库stamps
  • 地址: https://stampit.js.org
  • git: https://github.com/stampit-org/stampit

牛的要死, 最初的版本只有90行代码. 现在的版本有400行, 但是, 整个项目的测试代码有几千行. 腻害哦.

更基础的基础知识

  • lambda和闭包, 函数可以作为参数和返回值使用.
  • 对象字面量, 数组字面量, 正则字面量, 字面量是王道.
  • 动态对象扩展.
  • 原型, 可以clone
  • 工厂函数, 完全可以替代构造函数.
  • 流式api与链式调用.
原型有两种打开方式
  1. 原型代理, object.create就是原型代理. 实际就是指定了新的对象的prototype. 原型上的数据天生就是分享的, 就是享元模式.
  2. 原型克隆, object.assign就差不多是克隆了, 完全复制一套属性给新的对象.
对象的构造
  1. 构造函数, 这个不推荐, 虽然我用的很熟, 但是确实不好用.
  2. 字面量, 这个效果拔群, 能用尽量用.
  3. 工厂函数, 这个确实好用. 私有的, 共有的(全局且私有)……
//前面的extend等函数存在的情况下
const cprototype={}, //一个用作prototype的字面量, 方法属性都放里面.
car= function car(opt){
  return extend(Object.create(cprototype),opt);
  /** 这个目标是可以任意指定对象的属性. 不指定就是默认属性. 
   * 不需要一堆this.xxx=xxx了. 这个新的对象他的原型就是cprototype.
   * 同时他会把opt的内容copy进来, 可以覆盖掉原本的默认值.
   */
},
mycar = car({color: 'red'}); //这里得到一个新的对象. 

关于stamp: 现代的方案有所调整, 参考姊妹篇: 2019-05-08-stamp或者是一条出路

object很关键
//类方法

Object.assign()
Copies the values of all enumerable own properties from one or more source objects to a target object.

Object.create(原型, 属性对象) //制造一个object, 按照原型和属性
Creates a new object with the specified prototype object and properties.

Object.defineProperty()
Adds the named property described by a given descriptor to an object.

Object.defineProperties()
Adds the named properties described by the given descriptors to an object.

Object.entries()
Returns an array of a given objects own enumerable property [key, value] pairs.

Object.freeze()
Freezes an object: other code cant delete or change any properties.


Object.keys() , 拿到所有键, 作为数组.
Object.values(), 拿到对象中的所有键值对的值, 作为数组.

解构和展开 destructuring assignment object spread
{xxx, oo}=p;
{...p};
const allRules = {...obj1, ...obj2, ...obj3};
[a, b, ...rest] = [10, 20, 30, 40, 50];
{a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}; //rest = {c: 30, d: 40}
[a=5, b=7] = [1]; //带默认值.
[a, b] = [b, a]; //可以做交换.

//参数也可以
function drawES2015Chart({size = 'big', coords = {x: 0, y: 0}, radius = 25} = {}) {
  console.log(size, coords, radius);
  // do some chart drawing
}

drawES2015Chart({
  coords: {x: 18, y: 30},
  radius: 30
});

//循环也能用
for (var {name: n, family: {father: f}} of people) {
  console.log('Name: ' + n + ', Father: ' + f);
}


//中括号代表字面量
let key = 'z';
let {[key]: foo} = {z: 'bar'};

console.log(foo); // "bar"


const props = [
  { id: 1, name: 'Fizz'},
  { id: 2, name: 'Buzz'},
  { id: 3, name: 'FizzBuzz'}
];

const [,, { name }] = props;

console.log(name); // "FizzBuzz"
对象的遍历
for (var i in obj) { //这个要筛掉原型链上的属性
  // obj.hasOwnProperty() is used to filter out properties from the object's prototype chain
  if (obj.hasOwnProperty(i)) {
  }
}

Object.keys  //key数组
Object.values  //value数组
Object.entries //[key, value]的数组

forEach   //object木有foreach
for of //他要求这个对象是iterable, 也就是要有iterator

xxx.keys() //行吗?
//不行, 除非iterable