function
Javascript定义类(class)的三种方法紫陌兰溪关注
function Obj() { var a = 0; //私有变量 var fn = function(){} //私有函数 Obj.a1 = 1; //静态变量 Obj.fn1 = function(){} //静态函数 this.a2 = 2; //实例变量 this.fn2 = function(){} //实例函数 } var o = new Obj(); console.log(o.a2); //2 console.log(o.a) //undefined console.log(o.a1); //undefined console.log(Obj.a1) //1 var o1 = {} var o2 = new Object(); var f1 = function() {}; var f2 = new Function('str', 'consoloe.log(str)'); console.log(typeof o); //object console.log(typeof o1); //object console.log(typeof o2); //object console.log(typeof f1); //function console.log(typeof f2); //function console.log(typeof o.fn2); //function JS中万物该对象,分为普通对象Object和函数对象function。 Obj本质是通过new Function创建的函数对象 原型链执行过程: 1.代码读取某个对象的某个属性的时候,搜索具有给定名字的属性, 2.搜索首先从对象实例开始,如果在实例中找到该属性则返回, 3.如果没有则查找prototype,如果还是没有找到 4.则继续递归prototype的prototype对象,直到找到为止, 5.如果递归到object仍然没有则返回错误。 JS在创建对象时,都有一个__proto__内置属性,用于指向创建它的函数对象的prototype,经过多重继承向上查找后,最终指向Object对象。 Objerct.__proto__指向null. 实例对过构造函数创建的,实例具有两个属性: 1.constructor 指向构造函数 2.__proto__ 指向原型对象 原型对象有一个指针指向构造函数 Person.prototype.constructor = Person; 通过return的形式暴露出简单的使用名称,以达到public/private的效果,修改后的代码如下: Calculator.prototype = function () { add = function (x, y) { return x + y; }, subtract = function (x, y) { return x - y; } return { add: add, subtract: subtract } } (); (new Calculator()).add(11, 3);
定义对象
Member = function(id, name) { this.id = id; this.name = name; } 或者 function Member(id,name) { this.id = id; this.name = name; this.showMe = function() { document.write(); } this.do = todo; } function todo() { alert('todo'); } Member.prototype.log = function() { alert('log'); } Member.prototype = { greet: function() { alert('hello' + this.name); } info : function() { alert('id:' + this.id + ', name:' + this.name); } } m1 = new Member(1, 'tom'); m2 = new Member(2,'jenny'); m1.showMe(); m2.showMe(); //函数定义在内部,每次构造实例,都会定义一次,消耗系统资源 m1.greet(); m2.greet(); //函数定义在prototype, 每个实例由prototype指向一个函数引用
继承
function Animal(name){ this.name = name; this.showName = function(){ alert(this.name); } } function Cat(name){ Animal.call(this, name); } var cat = new Cat("Black Cat"); cat.showName(); 或者: Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物 或者: Cat.prototype = Animal.prototype; Cat.prototype.constructor = Cat; var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物 或者: var F = function(){}; F.prototype = Animal.prototype; Cat.prototype = new F(); Cat.prototype.constructor = Cat; 将上面的方法,封装成一个函数,便于使用。 function extend(Child, Parent) { var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.uber = Parent.prototype; } uber是一个德语词,意思是"向上"、"上一层",即保存了父类的prototype 使用的时候,方法如下 extend(Cat,Animal); var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物 这个extend函数,就是YUI库如何实现继承的方法
拷贝继承
function extend2(Child, Parent) { var p = Parent.prototype; var c = Child.prototype; for (var i in p) { c[i] = p[i]; } c.uber = p; } 使用的时候,这样写: extend2(Cat, Animal); var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物
非构造函数的继承
有一个对象,叫做"中国人"。 var Chinese = { nation:'中国' }; 还有一个对象,叫做"医生"。 var Doctor ={ career:'医生' } function object(o) { function F() {} F.prototype = o; return new F(); } 使用的时候,第一步先在父对象的基础上,生成子对象: var Doctor = object(Chinese); 然后,再加上子对象本身的属性: Doctor.career = '医生'; 这时,子对象已经继承了父对象的属性了。 alert(Doctor.nation); //中国
浅拷贝
function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } c.uber = p; return c; } 使用的时候,这样写: var Doctor = extendCopy(Chinese); Doctor.career = '医生'; alert(Doctor.nation); // 中国
深拷贝
function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c; } 使用的时候这样写: var Doctor = deepCopy(Chinese); 现在,给父对象加一个属性,值为数组。然后,在子对象上修改这个属性: Chinese.birthPlaces = ['北京','上海','香港']; Doctor.birthPlaces.push('厦门'); 这时,父对象就不会受到影响了。 alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门 alert(Chinese.birthPlaces); //北京, 上海, 香港 目前,jQuery库使用的就是这种继承方法。