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库使用的就是这种继承方法。