你不知道的JavaScript--面向对象高级程序设计

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

1. JS是基于原型的程序

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

function Aaa(){
    this.name = ‘小明‘;
}
Aaa.prototype.showName = function(){
    alert( this.name );
};

var a1 = new Aaa();
a1.showName();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

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

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

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

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

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

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

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

var arr = [1,2,3];
Array.prototype.push = function(){
    //this : 1,2,3
    //arguments : 4,5,6

    for(var i=0;i<arguments.length;i++){
        this[this.length] = arguments[i]
    }

    return this.length;
};

arr.push(4,5,6);

alert( arr );*/

//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.但是当你看到下面的代码时,你发现了什么?

var str = ‘hello‘;

alert( typeof str );//String

str.charAt(0);
str.indexOf(‘e‘);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

var str = new String(‘hello‘);//通过构造函数构造的数据类型就是对象了,可以直接调用方法了

//alert( typeof str );

alert(str.charAt(1));

String.prototype.charAt = function(){};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

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

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

var str = ‘hello‘;

String.prototype.lastValue = function(){
    return this.charAt(this.length-1);
};

alert( str.lastValue() ); //o
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

var str = ‘hello‘;

str.number = 10;

alert( str.number );  //undefined
  • 1
  • 2
  • 3
  • 4
  • 5

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

3. JS中的原型链

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

原型链的最外层是Object。

function Aaa(){

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

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

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

假如这样呢?

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

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

function Aaa(){
    //this.num = 20;
}
//Aaa.prototype.num = 10;
Object.prototype.num = 30;

var a1 = new Aaa();
alert(a1.num);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

  • hasOwnProperty() : 看是不是对象自身下面的属性
var arr = [];
arr.num = 10;
Array.prototype.num2 = 20;

//alert(  arr.hasOwnProperty(‘num‘)  );  //true

alert(  arr.hasOwnProperty(‘num2‘)  );  //false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • constructor : 查看对象的构造函数

    • 每个原型都会自动添加constructor属性
    • For in 的时候有些属性是找不到的
    • 避免修改construtor属性
function Aaa(){
}

var a1 = new Aaa();

alert( a1.constructor );  //Aaa

var arr = [];
alert( arr.constructor == Array );  //true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

function Aaa(){
}
//Aaa.prototype.constructor = Aaa;   //每一个函数都会有的,都是自动生成的

//Aaa.prototype.constructor = Array;

var a1 = new Aaa();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
alert( a1.hasOwnProperty == Object.prototype.hasOwnProperty );  //true

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

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

function Aaa(){
}

Aaa.prototype.name = ‘小明‘;//采用这种原型继承,constructor没有改变
Aaa.prototype.age = 20;

Aaa.prototype = {//采用json格式的对象,这就是相当于一个Object对象赋值,所以constructor变为了Object。
    constructor : Aaa,
    name : ‘小明‘,
    age : 20
};

var a1 = new Aaa();
alert( a1.constructor );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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

function Aaa(){
}

Aaa.prototype.name = 10;
Aaa.prototype.constructor = Aaa;

for( var attr in Aaa.prototype ){
    alert(attr);//只有name
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • instanceof : 运算符。对象与构造函数在原型链上是否有关系【对象是否是构造函数的一个实例】
function Aaa(){
}

var a1 = new Aaa();

//alert( a1 instanceof Object );  //true

var arr = [];

alert( arr instanceof Array );//true;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • toString() : 系统对象下面都是自带的 , 自己写的对象都是通过原型链找object下面的。主要做一些解析,主要用于Array、Boolean、Date、Object、Number等对象
var arr = [];
alert( arr.toString == Object.prototype.toString ); //false*/

/*function Aaa(){
}
var a1 = new Aaa();
alert( a1.toString == Object.prototype.toString );  //true*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
- 把对象转成字符串
/*var arr = [1,2,3];

    Array.prototype.toString = function(){
        return this.join(‘+‘);
    };

    alert( arr.toString() );  //‘1+2+3‘*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 做进制转换,默认10进制
//var num = 255;
    //alert( num.toString(16) );  //‘ff‘
  • 1
  • 2
  • 最重要一点是做类型判断
//利用toString做类型的判断 : 

/*var arr = [];

alert( Object.prototype.toString.call(arr) == ‘[object Array]‘ ); */
//‘[object Array]‘
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

alert( arr.constructor == Array );  

alert( arr instanceof Array );  

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

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

window.onload = function(){

    var oF = document.createElement(‘iframe‘);
    document.body.appendChild( oF );

    var ifArray = window.frames[0].Array;

    var arr = new ifArray();

    //alert( arr.constructor == Array );  //false

    //alert( arr instanceof Array );  //false

    alert( Object.prototype.toString.call(arr) == ‘[object Array]‘ );  //true
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

5. JS对象的继承

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

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

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

1.原型继承

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

function SuperType(){
    this.property = true;
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
};

function SubType(){
    this.subproperty = false;
}
//继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
    return this.subproperty;
};

var instance = new SubType();
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()方法。

alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true

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

原型继承注意点:

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

function SuperType(){
    this.property = true;
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
};
function SubType(){
    this.subproperty = false;
}
//继承了SuperType
SubType.prototype = new SuperType();
//添加新方法,一定放在原型替换之后,不然会被覆盖掉的哦。
SubType.prototype.getSubValue = function (){
    return this.subproperty;
};
    //重写超类型中的方法
    SubType.prototype.getSuperValue = function (){
        return false;
    };
    var instance = new SubType();
    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取代。

function SuperType(){
    this.property = true;
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
};
function SubType(){
    this.subproperty = false;
}
//继承了SuperType
SubType.prototype = new SuperType();
//使用字面量添加新方法,会导致上一行代码无效
SubType.prototype = {
    getSubValue : function (){
        return this.subproperty;
    },
    someOtherMethod : function (){
        return false;
    }
};
var instance = new SubType();
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

原型链的问题

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

function SuperType(){
    this.colors = ["red", "blue", "green"];
}
function SubType(){
}
//继承了SuperType
SubType.prototype = new SuperType();

var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"

var instance2 = new SubType();
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()方法也可以在(将来)新创建的对象上执行构造函数

function SuperType(){
    this.colors = ["red", "blue", "green"];
}
function SubType(){
    //继承了SuperType
    SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"

var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

传递参数

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

function SuperType(name){
    this.name = name;
}
function SubType(){
    //继承了SuperType,同时还传递了参数
    SuperType.call(this, "Nicholas");
    //实例属性
    this.age = 29;
}

var instance = new SubType();
alert(instance.name); //"Nicholas";
alert(instance.age); //29
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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

借用构造函数的问题

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

3. 组合继承

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

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};

function SubType(name, age){
    //继承属性
    SuperType.call(this, name);
    this.age = age;
}

//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    alert(this.age);
};

var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29

var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
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.拓展:拷贝继承

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

var a = {
    name : ‘小明‘
};

var b = a;

b.name = ‘小强‘;

alert( a.name );//小强
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

var a = {
    name : ‘小明‘
};

//var b = a;
var b = {};
extend( b , a );
b.name = ‘小强‘;
alert( a.name );    

function extend(obj1,obj2){
    for(var attr in obj2){
        obj1[attr] = obj2[attr];
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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

//继承 : 子类不影响父类,子类可以继承父类的一些功能 ( 代码复用 )

//属性的继承 : 调用父类的构造函数 call

//方法的继承 : for in :  拷贝继承 (jquery也是采用拷贝继承extend)

function CreatePerson(name,sex){   //父类
    this.name = name;
    this.sex = sex;
}
CreatePerson.prototype.showName = function(){
    alert( this.name );
};

var p1 = new CreatePerson(‘小明‘,‘男‘);
//p1.showName();

function CreateStar(name,sex,job){  //子类

    CreatePerson.call(this,name,sex);

    this.job = job;

}

//CreateStar.prototype = CreatePerson.prototype;

extend( CreateStar.prototype , CreatePerson.prototype );

CreateStar.prototype.showJob = function(){
};

var p2 = new CreateStar(‘黄晓明‘,‘男‘,‘演员‘);

p2.showName();

function extend(obj1,obj2){
    for(var attr in obj2){
        obj1[attr] = obj2[attr];
    }
}
  • 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.实例:用继承实现拖拽

<!DOCTYPE html>
<html>
<head>
    <title>拖拽继承</title>
    <style type="text/css">
        #div1{width: 100px;height: 100px;background: red;position: absolute;}
        #div2{width: 100px;height: 100px;background: blue;position: absolute;left: 100px;}
    </style>
</head>

<body>
<div id="div1"></div>
<div id="div2"></div>

<script type="text/javascript">

window.onload = function(){
    var d1 = new Drag(‘div1‘);
    d1.init();

    var d2 = new childDrag(‘div2‘);
    d2.init();
}

function Drag(id){
    this.obj = document.getElementById(id);//定义拖拽的对象
    this.disX = 0;//水平边距
    this.disY = 0;//垂直边距
}

Drag.prototype.init = function(){//拖拽函数
    var that = this;
    this.obj.onmousedown = function(e){
        var e = e || window.event;
        that.fnDown(e);

        document.onmousemove = function(e){
            var e = e || window.evnet;
            that.fnMove(e);
        }
        document.onmouseup = function(){
            that.fnUP();
        }
        return false;
    }

}

Drag.prototype.fnDown = function(e){
    //clientX 返回当事件被触发时,鼠标指针的水平坐标
    //offsetLeft:获取对象相对于版面左侧位置
    this.disX = e.clientX - this.obj.offsetLeft;//鼠标位置到obj左边位置
    this.disY = e.clientY - this.obj.offsetTop;
}

Drag.prototype.fnMove = function(e){
    this.obj.style.left = e.clientX - this.disX + ‘px‘;
    this.obj.style.top = e.clientY - this.disY +‘px‘;
}

Drag.prototype.fnUP = function(){
    document.onmousedown= null;
    document.onmousemove = null;
}

//定义子类,子类继承父类,但是与父类有不同,不能拖拽脱离可视区域

function childDrag(id){
    Drag.call(this,id);//属性用call,apply
}

// 方法用for in
extend(childDrag.prototype,Drag.prototype);

//重写父类的方法
childDrag.prototype.fnMove = function(e){
    var leftX = e.clientX - this.disX;
    var topY = e.clientY - this.disY;
    var clientW = document.documentElement.clientWidth - this.obj.offsetWidth;
    var clientH = document.documentElement.clientHeight  - this.obj.offsetHeight;

    if (leftX < 0){
        leftX = 0;
    }else if (leftX >clientW) {
        leftX = clientW;
    }

    if (topY < 0 ) {
        topY = 0;
    }else if (topY> clientH) {
        topY = clientH;
    }

    this.obj.style.left = leftX + ‘px‘;
    this.obj.style.top = topY + ‘px‘;
}

function extend(obj1, obj2){//拷贝函数
    for(var attr in obj2){
        obj1[attr] = obj2[attr];
    }
}

</script>
</body>
</html>
时间: 2024-10-29 12:22:05

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

你不知道的JavaScript--Item37 面向对象高级程序设计

1. JS是基于原型的程序 建立一个简单的面向对象的类.有属性,有方法. function Aaa(){ this.name = '小明'; } Aaa.prototype.showName = function(){ alert( this.name ); }; var a1 = new Aaa(); a1.showName(); 在JS的自身的对象中,也是new一个对象,然后调用方法,比如: var arr = new Array(); arr.push(); arr.sort(); 在JS

《javascript》高级程序设计——类型转换错误

容易发生类型转换错误的另一个地方,就是流控制语句.像if之类的语句在确定下一步操作之前,会自动把任何值转换成布尔值.尤其是if语句,如果使用不当,最容易出错.来看下面的例子. function concat(str1,str2,str3){ var result= str1 + str2; if (str3){ //绝对不要这样 result += str3; } return result; } 这个函数的用意是拼接两或三个字符串,然后返回结果.其中,第三个字符串是可选的,因此必须要检查.第3

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

首先,JavaScript 面向对象的程序设计,主要分三部分. 理解对象属性: 理解并创建对象: 理解继承. 本文主要从第一方面来阐述: 理解对象属性 首先我们来理解Javascript对象是什么?在Javascript中,万物皆对象.其中创建自定义对象的最简单的方式就是创建一个Object的实例,如下: ECMAScript中有两种属性:数据属性和访问器属性. 数据属性:其中数据属性有四个描述其行为的特性:Configurable: 表示能都通过delete删除属性从而重新定义属性.Enume

JavaScript 面向对象的程序设计记录笔记2(设计模式)

以下为JavaScript高级程序设计 第六章面向对象的程序设计6.2节 创建对象(设计模式部分)读书记录. 1)工厂模式: function createPerson(name, age, sex) { var o = new Obejct(); o.age = age; o.sex = sex; o.name = name; return o; } var person = createPerson('Tom', 12, 'male'); var person = createPerson(

JavaScript 面向对象的程序设计记录笔记

以下为JavaScript高级程序设计第六章面向对象的程序设计读书笔记记录. 对象存在两个属性: 数据属性/ 访问器属性. 数据属性包括四个值: Configurable: 默认值为true, 表示能否通过delete删除属性重新定义:能否修改属性特性,或者能否吧属性修改为访问器属性. Enumable:  表示能否通过for in循环返回属性.默认值为true. writable: 表示能否修改属性,默认值为true. Value:包含这个属性的数据值. 访问器属性包括四个值:Configur

JavaScript Item37—— 面向对象高级程序设计

1. JS是基于原型的程序 建立一个简单的面向对象的类.有属性,有方法. <code class="hljs javascript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre

JavaScript学习--Item37 面向对象高级程序设计

1. JS是基于原型的程序 建立一个简单的面向对象的类.有属性,有方法. function Aaa(){ this.name = '小明'; } Aaa.prototype.showName = function(){ alert( this.name ); }; var a1 = new Aaa(); a1.showName(); 在JS的自身的对象中,也是new一个对象,然后调用方法,比如: var arr = new Array(); arr.push(); arr.sort(); 在JS

Javascript面向对象的程序设计

面向对象的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象. 每个对象都是基于一个引用类型创建的,这个引用类型可以是之前的原生类型,也可以是开发人员定义的类型. 1.理解对象 ①属性类型:ECMAScript中有两种属性:数据属性和访问器属性. (1)数据属性:数据属性包含一个数据值的位置.在这个位置可以读取和写入值,数据户型有4个描述其行为的特性: 数据属性有4个描述其行为的特性. [[Configurable]]:表示能否通过delete删除属性从而重

对象的概念——javascript面向对象高级

什么是对象? a.对现实事物的抽象     -面向对象是对现实事物的抽象 b.对数据的封装    -是对具体数据的封装,是一堆属性和方法的集合 对象的三大特征(封装.继承.多态) 1.封装性,是对属性和方法的封装 2.继承是将别人没有的,拿过来成为自己的就是继承,js里不具备特定的继承的机制,但是可以通过技术上实 3.多态,不同情况的不同表现形式.如某个方法,传一个参数和传多个参数,得到的结果不一样 ## 创建对象的四种方式 ## **  1.声明范式** // var obj = {} **2

闭包 —JavaScript面向对象高级

# 闭包 # 我的理解:面试时,先说作用域链,再说闭包产生的原因,然后是垃圾回收GC,最后说闭包. a.一个函数内部声明的变量,就是它的私有变量. b.在javascript中特性中,函数是可以访问它所在作用域链的所有变量. c.但函数外部是不能直接访问函数内部的私有变量 D.通过函数内部再嵌套函数,子函数返回父函数的变量,就创建了一个闭包. 闭包的表现形式 模块化的本质:是通过函数的局部作用域特性来产生局部上下文来保存局部变量 1.函数作为返回值 function fn(){ var coun