转载http://blog.csdn.net/i10630226/article/details/51088841

1. JS是基于原型的程序

建立一个简单的面向对象的类。有属性,有方法。

  1. function Aaa(){
  2. this.name = '小明';
  3. }
  4. Aaa.prototype.showName = function(){
  5. alert( this.name );
  6. };
  7. var a1 = new Aaa();
  8. a1.showName();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在JS的自身的对象中,也是new一个对象,然后调用方法,比如:

  1. var arr = new Array();
  2. arr.push();
  3. arr.sort();
  • 1
  • 2
  • 3

在JS源码 : 系统对象也是基于原型的程序。比如:

  1. function Array(){
  2. this.lenglth = 0;
  3. }
  4. Array.prototype.push = function(){};
  5. Array.prototype.sort = function(){};
  • 1
  • 2
  • 3
  • 4
  • 5

尽量不要去修改或者添加系统对象下面的方法和属性,这样会改变系统的方法。

  1. var arr = [1,2,3];
  2. Array.prototype.push = function(){}
  3. arr.push(4,5,6);
  4. alert( arr );
  • 1
  • 2
  • 3
  • 4

这样修改后,push方法就失效了,覆盖了JS本省的push方法。

那么如何自己重写Array的push方法呢?

  1. var arr = [1,2,3];
  2. Array.prototype.push = function(){
  3. //this : 1,2,3
  4. //arguments : 4,5,6
  5. for(var i=0;i<arguments.length;i++){
  6. this[this.length] = arguments[i]
  7. }
  8. return this.length;
  9. };
  10. arr.push(4,5,6);
  11. alert( arr );*/
  12. //pop shift unshift splice sort
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

2.JS中的包装对象

我们知道js的基本数据类型有 string, number, boolean, null, undefined, object.但是当你看到下面的代码时,你发现了什么?

  1. var str = 'hello';
  2. alert( typeof str );//String
  3. str.charAt(0);
  4. str.indexOf('e');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

除了对象可以调用方法,为什么基本数据类型也可以?这是因为在js中,string, number, boolean都有自己的包装对象。String Number Boolean

  1. var str = new String('hello');//通过构造函数构造的数据类型就是对象了,可以直接调用方法了
  2. //alert( typeof str );
  3. alert(str.charAt(1));
  4. String.prototype.charAt = function(){};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

那基本类型调用方法时,发生了什么呢?

  1. var str = 'hello';
  2. str.charAt(0); //基本类型会找到对应的包装对象类型,然后包装对象把所有的属性和方法给了基本类型,然后包装对象消失,包装类型就和快递员一样。
  • 1
  • 2

比如要实现字符串的一个lastValue方法:

  1. var str = 'hello';
  2. String.prototype.lastValue = function(){
  3. return this.charAt(this.length-1);
  4. };
  5. alert( str.lastValue() ); //o
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

str通过原型继承,使本身具有了lastValue()方法,所以可以直接调用,我们再来看个例子:

  1. var str = 'hello';
  2. str.number = 10;
  3. alert( str.number ); //undefined
  • 1
  • 2
  • 3
  • 4
  • 5

这里为什么是undefined,因为这里包装类型并没有把number共享给str,只是自己有,而复制完消失,str.name没有接受到值,变成undefined。

3. JS中的原型链

在js中,实例对象与原型之间的连接,叫做原型链,原型链之间的连接叫__proto__( 隐式连接 )

原型链的最外层是Object。

  1. function Aaa(){
  2. }
  3. Aaa.prototype.num = 10;
  4. var a1 = new Aaa();
  5. alert(a1.num);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

比如我们一般的定义一个对象Aaa,并在原型上定义了一个属性num,新new的a1是怎么访问到原型上的属性的呢?

这里就是a1有一个__proto__属性,指向Aaa.prototype原型对象,顾可以访问到。

假如这样呢?

  1. function Aaa(){
  2. this.num = 20;
  3. }
  4. Aaa.prototype.num = 10;
  5. var a1 = new Aaa();
  6. alert(a1.num);//20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里有两个num,弹出的是哪一个呢?这就是原型链的规则,先从本身对象找,本身对象没有到原型对象上找,。。。。。一直找下去,何处是尽头?知道找到object的原型,如果没有就报错,因为object的原型是null,这个原型连接起来的链就是一条原型链。看例子

  1. function Aaa(){
  2. //this.num = 20;
  3. }
  4. //Aaa.prototype.num = 10;
  5. Object.prototype.num = 30;
  6. var a1 = new Aaa();
  7. alert(a1.num);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4. 面向对象的一些常用属性和方法

  • hasOwnProperty() : 看是不是对象自身下面的属性
  1. var arr = [];
  2. arr.num = 10;
  3. Array.prototype.num2 = 20;
  4. //alert( arr.hasOwnProperty('num') ); //true
  5. alert( arr.hasOwnProperty('num2') ); //false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • constructor : 查看对象的构造函数

    • 每个原型都会自动添加constructor属性
    • For in 的时候有些属性是找不到的
    • 避免修改construtor属性
  1. function Aaa(){
  2. }
  3. var a1 = new Aaa();
  4. alert( a1.constructor ); //Aaa
  5. var arr = [];
  6. alert( arr.constructor == Array ); //true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

每个对象的原型的构造函数都自动指向本身,可以修改为别的,但是不建议修改:

  1. function Aaa(){
  2. }
  3. //Aaa.prototype.constructor = Aaa; //每一个函数都会有的,都是自动生成的
  4. //Aaa.prototype.constructor = Array;
  5. var a1 = new Aaa();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. alert( a1.hasOwnProperty == Object.prototype.hasOwnProperty ); //true

说明hasOwnProperty 属性是通过原型链,在Object.prototype原型上的。

有时候我们会不经意的就把原型修改了,这个时候我们就要把原型修正一下:

  1. function Aaa(){
  2. }
  3. Aaa.prototype.name = '小明';//采用这种原型继承,constructor没有改变
  4. Aaa.prototype.age = 20;
  5. Aaa.prototype = {//采用json格式的对象,这就是相当于一个Object对象赋值,所以constructor变为了Object。
  6. constructor : Aaa,
  7. name : '小明',
  8. age : 20
  9. };
  10. var a1 = new Aaa();
  11. alert( a1.constructor );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

采用for in循环,是循环不到原型上constructor属性的。

  1. function Aaa(){
  2. }
  3. Aaa.prototype.name = 10;
  4. Aaa.prototype.constructor = Aaa;
  5. for( var attr in Aaa.prototype ){
  6. alert(attr);//只有name
  7. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • instanceof : 运算符。对象与构造函数在原型链上是否有关系【对象是否是构造函数的一个实例】
  1. function Aaa(){
  2. }
  3. var a1 = new Aaa();
  4. //alert( a1 instanceof Object ); //true
  5. var arr = [];
  6. alert( arr instanceof Array );//true;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • toString() : 系统对象下面都是自带的 , 自己写的对象都是通过原型链找object下面的。主要做一些解析,主要用于Array、Boolean、Date、Object、Number等对象
  1. var arr = [];
  2. alert( arr.toString == Object.prototype.toString ); //false*/
  3. /*function Aaa(){
  4. }
  5. var a1 = new Aaa();
  6. alert( a1.toString == Object.prototype.toString ); //true*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. - 把对象转成字符串
  1. /*var arr = [1,2,3];
  2. Array.prototype.toString = function(){
  3. return this.join('+');
  4. };
  5. alert( arr.toString() ); //'1+2+3'*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 做进制转换,默认10进制
  1. //var num = 255;
  2. //alert( num.toString(16) ); //'ff'
  • 1
  • 2
  • 最重要一点是做类型判断
  1. //利用toString做类型的判断 :
  2. /*var arr = [];
  3. alert( Object.prototype.toString.call(arr) == '[object Array]' ); */
  4. //'[object Array]'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

类型判断的常用方法:三种typeof是不行的,根本区分不开。假如判断一个数据类型是数组?

  1. alert( arr.constructor == Array );
  2. alert( arr instanceof Array );
  3. alert( Object.prototype.toString.call(arr) == '[object Array]' );
  • 1
  • 2
  • 3
  • 4
  • 5

但是在一种很特殊的情况下,就只能用第三种,在iframe中创建一个数组,前两种方法就会失效,但是在大多数情况下,还是可以的。

  1. window.onload = function(){
  2. var oF = document.createElement('iframe');
  3. document.body.appendChild( oF );
  4. var ifArray = window.frames[0].Array;
  5. var arr = new ifArray();
  6. //alert( arr.constructor == Array ); //false
  7. //alert( arr instanceof Array ); //false
  8. alert( Object.prototype.toString.call(arr) == '[object Array]' ); //true
  9. };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

5. JS对象的继承

什么是继承?
在原有对象的基础上,略作修改,得到一个新的对象不影响原有对象的功能。

其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。

构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针_proto_

1.原型继承

实现原型链有一种基本模式,其代码大致如下:

  1. function SuperType(){
  2. this.property = true;
  3. }
  4. SuperType.prototype.getSuperValue = function(){
  5. return this.property;
  6. };
  7. function SubType(){
  8. this.subproperty = false;
  9. }
  10. //继承了SuperType
  11. SubType.prototype = new SuperType();
  12. SubType.prototype.getSubValue = function (){
  13. return this.subproperty;
  14. };
  15. var instance = new SubType();
  16. alert(instance.getSuperValue()); //true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

以上代码定义了两个类型:SuperType 和SubType。每个类型分别有一个属性和一个方法。它们的主要区别是SubType 继承了SuperType,而继承是通过创建SuperType 的实例,并将该实例赋给SubType.prototype 实现的。实现的本质是重写原型对象,代之以一个新类型的实例。换句话说,原来存在于SuperType 的实例中的所有属性和方法,现在也存在于SubType.prototype 中了。在确立了继承关系之后,我们给SubType.prototype 添加了一个方法,这样就在继承了SuperType 的属性和方法的基础上又添加了一个新方法。这个例子中的实例以及构造函数和原型之间的关系如图

我们没有使用SubType 默认提供的原型,而是给它换了一个新原型;这个新原型就是SuperType 的实例。于是,新原型不仅具有作为一个SuperType 的实例所拥有的全部属性和方法,而且其内部还有一个指针,指向了SuperType 的原型。

我们知道,所有引用类型默认都继承了Object,而这个继承也是通过原型链实现的,上面例子展示的原型链中还应该包括另外一个继承层次。

可以通过两种方式来确定原型和实例之间的关系instanceof操作符,isPrototypeOf()方法。

  1. alert(instance instanceof Object); //true
  2. alert(instance instanceof SuperType); //true
  3. alert(instance instanceof SubType); //true
  4. alert(Object.prototype.isPrototypeOf(instance)); //true
  5. alert(SuperType.prototype.isPrototypeOf(instance)); //true
  6. alert(SubType.prototype.isPrototypeOf(instance)); //true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

原型继承注意点:

(1)子类型有时候需要重写父类型中的某个方法,或者需要添加超类型中不存在的某个方法。但不管怎
样,给原型添加方法的代码一定要放在替换原型的语句之后。

  1. function SuperType(){
  2. this.property = true;
  3. }
  4. SuperType.prototype.getSuperValue = function(){
  5. return this.property;
  6. };
  7. function SubType(){
  8. this.subproperty = false;
  9. }
  10. //继承了SuperType
  11. SubType.prototype = new SuperType();
  12. //添加新方法,一定放在原型替换之后,不然会被覆盖掉的哦。
  13. SubType.prototype.getSubValue = function (){
  14. return this.subproperty;
  15. };
  16. //重写超类型中的方法
  17. SubType.prototype.getSuperValue = function (){
  18. return false;
  19. };
  20. var instance = new SubType();
  21. alert(instance.getSuperValue()); //false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

(2)通过原型链实现继承时,不能使用对象字面量创建原型方法。因为这样做就会重写原型链,直接被json取代。

  1. function SuperType(){
  2. this.property = true;
  3. }
  4. SuperType.prototype.getSuperValue = function(){
  5. return this.property;
  6. };
  7. function SubType(){
  8. this.subproperty = false;
  9. }
  10. //继承了SuperType
  11. SubType.prototype = new SuperType();
  12. //使用字面量添加新方法,会导致上一行代码无效
  13. SubType.prototype = {
  14. getSubValue : function (){
  15. return this.subproperty;
  16. },
  17. someOtherMethod : function (){
  18. return false;
  19. }
  20. };
  21. var instance = new SubType();
  22. alert(instance.getSuperValue()); //error!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

原型链的问题

原型链虽然很强大,可以用它来实现继承,但它也存在一些问题。其中,最主要的问题来自包含引用类型值的原型。包含引用类型值的原型属性会被所有实例 共享;在通过原型来实现继承时,原型实际上会变成另一个类型的实例。于是,原来实例的属性也就顺理成章地变成了现在的原型属性了。引用类型共享了数 据。。。

  1. function SuperType(){
  2. this.colors = ["red", "blue", "green"];
  3. }
  4. function SubType(){
  5. }
  6. //继承了SuperType
  7. SubType.prototype = new SuperType();
  8. var instance1 = new SubType();
  9. instance1.colors.push("black");
  10. alert(instance1.colors); //"red,blue,green,black"
  11. var instance2 = new SubType();
  12. alert(instance2.colors); //"red,blue,green,black"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这个例子中的SuperType 构造函数定义了一个colors 属性,该属性包含一个数组(引用类型值)。SuperType 的每个实例都会有各自包含自己数组的colors 属性。当SubType 通过原型链继承了SuperType 之后,SubType.prototype 就变成了SuperType 的一个实例,因此它也拥有了一个它自己的colors 属性——就跟专门创建了一个SubType.prototype.colors 属性一样。但结果是什么呢?结果是SubType 的所有实例都会共享这一个colors 属性。而我们对instance1.colors 的修改能够通过instance2.colors 反映出来,就已经充分证实了这一点。

原型链的第二个问题是:在创建子类型的实例时,不能向超类型的构造函数中传递参数。实际上,应该说是没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。

2.构造函数继承(类式继承)

这种技术的基本思想相当简单,即在子类型构造函数的内部调用超类型构造函数。别忘了,函数只不过是在特定环境中执行代码的对象,因此通过使用apply()和call()方法也可以在(将来)新创建的对象上执行构造函数

  1. function SuperType(){
  2. this.colors = ["red", "blue", "green"];
  3. }
  4. function SubType(){
  5. //继承了SuperType
  6. SuperType.call(this);
  7. }
  8. var instance1 = new SubType();
  9. instance1.colors.push("black");
  10. alert(instance1.colors); //"red,blue,green,black"
  11. var instance2 = new SubType();
  12. alert(instance2.colors); //"red,blue,green"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

传递参数

相对于原型链而言,借用构造函数有一个很大的优势,即可以在子类型构造函数中向超类型构造函
数传递参数。

  1. function SuperType(name){
  2. this.name = name;
  3. }
  4. function SubType(){
  5. //继承了SuperType,同时还传递了参数
  6. SuperType.call(this, "Nicholas");
  7. //实例属性
  8. this.age = 29;
  9. }
  10. var instance = new SubType();
  11. alert(instance.name); //"Nicholas";
  12. alert(instance.age); //29
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在SubType 构造函数内部调用SuperType 构造函数时,实际上是为SubType 的实例设置了name 属性。为了确保SuperType 构造函数不会重写子类型的属性,可以在调用超类型构造函数后,再添加应该在子类型中定义的属性。

借用构造函数的问题

如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定义,因此函数复用就无从谈起了,而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。

3. 组合继承

将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。

  1. function SuperType(name){
  2. this.name = name;
  3. this.colors = ["red", "blue", "green"];
  4. }
  5. SuperType.prototype.sayName = function(){
  6. alert(this.name);
  7. };
  8. function SubType(name, age){
  9. //继承属性
  10. SuperType.call(this, name);
  11. this.age = age;
  12. }
  13. //继承方法
  14. SubType.prototype = new SuperType();
  15. SubType.prototype.constructor = SubType;
  16. SubType.prototype.sayAge = function(){
  17. alert(this.age);
  18. };
  19. var instance1 = new SubType("Nicholas", 29);
  20. instance1.colors.push("black");
  21. alert(instance1.colors); //"red,blue,green,black"
  22. instance1.sayName(); //"Nicholas";
  23. instance1.sayAge(); //29
  24. var instance2 = new SubType("Greg", 27);
  25. alert(instance2.colors); //"red,blue,green"
  26. instance2.sayName(); //"Greg";
  27. instance2.sayAge(); //27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

4.拓展:拷贝继承

先理解一下对象的拷贝,对象的引用是地址引用,双向改变。而基本数据类型是按值传递,不影响原来的数值。

  1. var a = {
  2. name : '小明'
  3. };
  4. var b = a;
  5. b.name = '小强';
  6. alert( a.name );//小强
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

采用拷贝继承的方式,将方法一个个拷贝过去就不会发生双向继承了。

  1. var a = {
  2. name : '小明'
  3. };
  4. //var b = a;
  5. var b = {};
  6. extend( b , a );
  7. b.name = '小强';
  8. alert( a.name );
  9. function extend(obj1,obj2){
  10. for(var attr in obj2){
  11. obj1[attr] = obj2[attr];
  12. }
  13. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

通过这个对象的复制之后,就可以实现拷贝继承了:

  1. //继承 : 子类不影响父类,子类可以继承父类的一些功能 ( 代码复用 )
  2. //属性的继承 : 调用父类的构造函数 call
  3. //方法的继承 : for in : 拷贝继承 (jquery也是采用拷贝继承extend)
  4. function CreatePerson(name,sex){ //父类
  5. this.name = name;
  6. this.sex = sex;
  7. }
  8. CreatePerson.prototype.showName = function(){
  9. alert( this.name );
  10. };
  11. var p1 = new CreatePerson('小明','男');
  12. //p1.showName();
  13. function CreateStar(name,sex,job){ //子类
  14. CreatePerson.call(this,name,sex);
  15. this.job = job;
  16. }
  17. //CreateStar.prototype = CreatePerson.prototype;
  18. extend( CreateStar.prototype , CreatePerson.prototype );
  19. CreateStar.prototype.showJob = function(){
  20. };
  21. var p2 = new CreateStar('黄晓明','男','演员');
  22. p2.showName();
  23. function extend(obj1,obj2){
  24. for(var attr in obj2){
  25. obj1[attr] = obj2[attr];
  26. }
  27. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

6.实例:用继承实现拖拽

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>拖拽继承</title>
  5. <style type="text/css">
  6. #div1{width: 100px;height: 100px;background: red;position: absolute;}
  7. #div2{width: 100px;height: 100px;background: blue;position: absolute;left: 100px;}
  8. </style>
  9. </head>
  10. <body>
  11. <div id="div1"></div>
  12. <div id="div2"></div>
  13. <script type="text/javascript">
  14. window.onload = function(){
  15. var d1 = new Drag('div1');
  16. d1.init();
  17. var d2 = new childDrag('div2');
  18. d2.init();
  19. }
  20. function Drag(id){
  21. this.obj = document.getElementById(id);//定义拖拽的对象
  22. this.disX = 0;//水平边距
  23. this.disY = 0;//垂直边距
  24. }
  25. Drag.prototype.init = function(){//拖拽函数
  26. var that = this;
  27. this.obj.onmousedown = function(e){
  28. var e = e || window.event;
  29. that.fnDown(e);
  30. document.onmousemove = function(e){
  31. var e = e || window.evnet;
  32. that.fnMove(e);
  33. }
  34. document.onmouseup = function(){
  35. that.fnUP();
  36. }
  37. return false;
  38. }
  39. }
  40. Drag.prototype.fnDown = function(e){
  41. //clientX 返回当事件被触发时,鼠标指针的水平坐标
  42. //offsetLeft:获取对象相对于版面左侧位置
  43. this.disX = e.clientX - this.obj.offsetLeft;//鼠标位置到obj左边位置
  44. this.disY = e.clientY - this.obj.offsetTop;
  45. }
  46. Drag.prototype.fnMove = function(e){
  47. this.obj.style.left = e.clientX - this.disX + 'px';
  48. this.obj.style.top = e.clientY - this.disY +'px';
  49. }
  50. Drag.prototype.fnUP = function(){
  51. document.onmousedown= null;
  52. document.onmousemove = null;
  53. }
  54. //定义子类,子类继承父类,但是与父类有不同,不能拖拽脱离可视区域
  55. function childDrag(id){
  56. Drag.call(this,id);//属性用call,apply
  57. }
  58. // 方法用for in
  59. extend(childDrag.prototype,Drag.prototype);
  60. //重写父类的方法
  61. childDrag.prototype.fnMove = function(e){
  62. var leftX = e.clientX - this.disX;
  63. var topY = e.clientY - this.disY;
  64. var clientW = document.documentElement.clientWidth - this.obj.offsetWidth;
  65. var clientH = document.documentElement.clientHeight - this.obj.offsetHeight;
  66. if (leftX < 0){
  67. leftX = 0;
  68. }else if (leftX >clientW) {
  69. leftX = clientW;
  70. }
  71. if (topY < 0 ) {
  72. topY = 0;
  73. }else if (topY> clientH) {
  74. topY = clientH;
  75. }
  76. this.obj.style.left = leftX + 'px';
  77. this.obj.style.top = topY + 'px';
  78. }
  79. function extend(obj1, obj2){//拷贝函数
  80. for(var attr in obj2){
  81. obj1[attr] = obj2[attr];
  82. }
  83. }
  84. </script>
  85. </body>
  86. </html>

你不知道的JavaScript--面向对象高级程序设计的更多相关文章

  1. JavaScript 面向对象的程序设计(一)之理解对象属性

    首先,JavaScript 面向对象的程序设计,主要分三部分. 理解对象属性: 理解并创建对象: 理解继承. 本文主要从第一方面来阐述: 理解对象属性 首先我们来理解Javascript对象是什么?在 ...

  2. 重学js之JavaScript 面向对象的程序设计(创建对象)

    注意: 本文章为 <重学js之JavaScript高级程序设计>系列第五章[JavaScript引用类型]. 关于<重学js之JavaScript高级程序设计>是重新回顾js基 ...

  3. JavaScript DOM 高级程序设计读书笔记一

    创建可重用的对象 简而言之,对象就是包含一组变量(称为属性)和函数(称为方法)的集合的实例.对象通常由类派生而来,而类中定义了对象拥有的属性和方法.如果你的脚本中都是对象之间的交互操作,那么就可以称之 ...

  4. JavaScript 面向对象的程序设计

    面向对象(Object-oriented,OO)的语言有一个标志,那就是它们都有类的概念.而通过类可以创建任意多个具有相同属性和方法的对象.前面提到过,ECMAScript中没有类的概念,因此它的对象 ...

  5. JavaScript面向对象的程序设计

    ECMAScript支持面对对象(oo)编程,但不使用类或接口.对象可以在代码执行过程中创建和增强,因此具有动态性而非严格定义的实体.在没有类的情况下,可以此采用下列模式创建对象. 工厂模式,使用简单 ...

  6. Learn JavaScript(面向对象的程序设计01)

    最新更新请访问: http://denghejun.github.io JavaScript与OOP   JavaScript作为web前端一种重要的脚本技术,已被大多开发人员所熟知.compare ...

  7. JavaScript DOM高级程序设计 7.向应用程序加入Ajax--我要坚持到底!

    有时候,或许是因为理解能力,也或许是因为浮躁,看东西总是不入心,而且还老是想跳过本节,或者赶紧看完本节,这样的恶性循环,让我在即没有真正的学习到知识,又打击我的学习信心,还浪费了我很多事件,我想,当遇 ...

  8. JavaScript DOM高级程序设计 4.3控制事件流和注册事件侦听器--我要坚持到底!

    一.事件流 我们通过下面一个实例,进行说明. <body> <h1>Event Flow</h1> <ul id="nav"> &l ...

  9. JavaScript DOM高级程序设计 3.6 实例 将HTML代码转换成DOM代码(附源码)--我要坚持到底!

    作为一名Web开发者,最讨厌的事情就是重复性任务,摆脱乏味的日常重复性事物的一种方法,是借助可重用的对象或者说与你现在建立的ADS库类似的库,另外一种让事情变得有意思,且能够加速开发进程的方式是编写能 ...

  10. JavaScript DOM高级程序设计 3.-DOM2和HTML2--我要坚持到底!

    由一个HTML进行说明,我就不敲了,直接copy <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" " ...

随机推荐

  1. 统计map上的read数量

    samtools flagstat /SRA111111/SRR111222/accepted_hits.bam 78406056 + 0 in total (QC-passed reads + QC ...

  2. JAVA开发--[二维码名片生成系统]

    上个月学校有个软件创新杯,最近看了网上很火的二维码比较不错.参考了国内国外一些技术文章,发现国外的确实好很多. 用的是QRcode包来实现的,基本常见的功能全部实现了. 因为刚学2个月,部分做得不是很 ...

  3. Spring + JDBC 组合开发集成步骤

    1:配置数据源,如: <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="h ...

  4. 编写spring配置文件时,不能出现帮助信息

    由于spring的schema文件位于网络上,如果机器不能连接到网络,那么在编写配置信息时候就无法出现提示信息,解决方法有两种: 1.让机器上网,eclipse会自动从网络上下载schema文件并缓存 ...

  5. poj1474Video Surveillance(半平面交)

    链接 半平面交的模板题,判断有没有核.: 注意一下最后的核可能为一条线,面积也是为0的,但却是有的. #include<iostream> #include <stdio.h> ...

  6. Java中值传递的实质,形式参数与实际参数。引用传递。

    值传递 package ch5; /** * Created by Jiqing on 2016/11/9. */ public class Transfer { public static void ...

  7. Jquery的普通事件和on的委托事件小案例

    以click的事件为例: 普通的绑定事件:$('.btn').click(function(){})绑定 on绑定事件:$(document).on('click','.btn2',function( ...

  8. VisualSVN官网

    VisualSVN是一款图形化svn服务器. http://www.visualsvn.com/

  9. LA 5135 Mining Your Own Business

    求出 bcc 后再……根据大白书上的思路即可. 然后我用的是自定义的 stack 类模板: #include<cstdio> #include<cstring> #includ ...

  10. spring+redis实现缓存

    spring + redis 实现数据的缓存 1.实现目标 通过redis缓存数据.(目的不是加快查询的速度,而是减少数据库的负担) 2.所需jar包 注意:jdies和commons-pool两个j ...