javascript笔记       

##javascript笔记

简单的脚本语言

###对象

http://www.cnblogs.com/dolphinX/p/3286177.html

JavaScript 是面向对象的语言,但 JavaScript 不使用类。

在 JavaScript 中,不会创建类,也不会通过类来创建对象(就像在其他面向对象的语言中那样)。

JavaScript 基于 prototype,而不是基于类的。

每个函数都有一个prototype属性,这个属性是指向一个对象的引用,这个对象称为原型对象,原型对象包含函数实例共享的方法和属性,也就是说将函数用作构造函数调用(使用new操作符调用)的时候,新创建的对象会从原型对象上继承属性和方法。

创建对象

1.
创建直接的实例
这个例子创建了对象的一个新实例,并向其添加了四个属性:
实例
person=new Object();
person.firstname="Bill";
person.lastname="Gates";
person.age=56;
person.eyecolor="blue";

2.
使用对象构造器
本例使用函数来构造对象:
实例
function person(firstname,lastname,age,eyecolor)
{
this.firstname=firstname;
this.lastname=lastname;
this.age=age;
this.eyecolor=eyecolor;
}
var myFather=new person("Bill","Gates",56,"blue");

私有变量、函数

function Obj(){
                var a=0; //私有变量
                var fn=function(){ //私有函数
                    
                }
            }

静态变量、函数

function Obj(){
                
            }
            
            Obj.a=0; //静态变量
            
            Obj.fn=function(){ //静态函数
                    
            }

实例变量、函数

function Obj(){
                this.a=[]; //实例变量
                this.fn=function(){ //实例方法
                    
                }
            }

如果函数里有定义函数,不同实例,会有多个相同函数,但多个函数内容都是一样的,应只保留一个函数,引入prototype。prototype维护一个函数列表,函数里有prototype属性指向这个prototype。有点像C++里的虚函数概念,类里面有虚函数指针指向虚函数表,表里都是虚函数地址。

###prototype

http://www.cnblogs.com/dolphinX/p/3286177.html

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,prototype里有一个构造函数constructor,指向的是该函数。

如果新建一个实例,实例会生成一个__proto__属性,指向的是函数的prototype.

###this

1.作为函数调用,this指全局对象

	var x = 1;
	function test(){
    alert(this.x);
  }
	test(); // 1   

2.作为对象方法的调用,this指对象

 function test(){
    alert(this.x);
  }
  var o = {};
  o.x = 1;
  o.m = test;
  o.m(); // 1    3.作为构造函数调用

  function test(){
    this.x = 1;
  }
  var o = new test();
  alert(o.x); // 1

###双向绑定

双向数据绑定指的是将对象属性变化绑定到UI

####双向绑定实现 #####观察者设计模式

订阅者在发布者那里注册回调函数,当发布者发生变化,则调用这些函数

function PubSub(){  
    var pubSub = {
        callbacks: {},
        on: function(msg,callback) {
            this.callbacks[msg] = this.callbacks[msg] || [];
            this.callbacks[msg].push(callback);
        },
        publish: function(msg) {
            this.callbacks[msg] = this.callbacks[msg] || [];
            for (var i = 0,len = this.callbacks[msg].length; i < len; i++) {
                this.callbacks[msg][i].apply(this,arguments);
            };
        }
      }
      return pubSub;
}

var writer = new PubSub();  
var reader = {  
    read: function(){alert("我读了这本新书")}
};
writer.on("newbook", function(){reader.read()});  
writer.publish("newbook");  

#####利用观察者模式实现

function DataBinder(object_id){
  // 创建一个简单的pubSub对象
  var pubSub = {
    callbacks: {},
    on: function(msg,callback) {
      this.callbacks[msg] = this.callbacks[msg] || [];
      this.callbacks[msg].push(callback);
    },
    publish: function(msg) {
      this.callbacks[msg] = this.callbacks[msg] || [];
      for (var i = 0,len = this.callbacks[msg].length; i < len; i++) {
        this.callbacks[msg][i].apply(this,arguments);
      };
    }
  },

      data_attr = "data-bind-" + object_id,
      message   = object_id + ":change",

      changeHandler = function(event) {
        var target    = event.target || event.srcElement, // IE8兼容
            prop_name = target.getAttribute(data_attr);

        if (prop_name && prop_name !== "") {
          pubSub.publish(message,prop_name,target.value);
        }
      };

  // 监听事件变化,并代理到pubSub
  if (document.addEventListener) {
    document.addEventListener("keyup",changeHandler,false);
  } else{
    // IE8使用attachEvent而不是addEventListenter
    document.attachEvent("onkeyup",changeHandler);
  };

  // pubSub将变化传播到所有绑定元素
  pubSub.on(message,function(event,prop_name,new_val){
    var elements = document.querySelectorAll("[" + data_attr + "=" +prop_name + "]"),
        tag_name;
    for (var i = 0,len = elements.length; i < len; i++) {
      tag_name = elements[i].tagName.toLowerCase();
      console.log(tag_name);
      if (tag_name === "input" || tag_name === "textarea" || tag_name === "select") {
        elements[i].value = new_val;
      } else{
        elements[i].innerHTML = new_val;
      };
      console.log("prop_name:"+new_val);
    };
  })

  return pubSub;
}

function User(uid) {
  var binder = new DataBinder(uid),
      user   = {
        attribute : {},

        // 属性设置器使用数据绑定器pubSub来发布
        set : function(attr_name,val) {
          this.attribute[attr_name] = val;
          binder.publish(uid + ":change",attr_name,val,this);
        },

        get : function(attr_name) {
          return this.attribute[attr_name];
        },

        _binder : binder
      };

  binder.on(uid + ":change",function(event,attr_name,new_val,initiator) {
    if (initiator !== user) {
      user.set(attr_name,new_val);
    }
  });

  return user;
}
var user = new User( 123 );
user.set( "name", "lwl" );


html:

<input type="text" data-bind-123="name" />
<p data-bind-123="name"></p>

ref: http://codepen.io/anon/pen/mRdLYd?editors=1010