javascript的对象、类和方法
1.类和对象的概念:
1.所有的事物都是一个对象,而类就是具有相同属性和行为方法的事物的集合
2.在JavaScript中建立对象的目的就是将所有的具有相同属性的行为的代码整合到一起,方便使用者的管理
3.类是具有相同特征和方法(行为)的事物的抽象,其中可以理解为:对象是类的实例,类是对象的实例
2.如何新建一个对象:
var str = "123" ; // string字符串 var str2 = new String("123"); // object对象
3.新建对象有以下两种方式:
//第一种方式 var obj = new Object(); console.log(typeof obj); // object对象 //第二种方式 var obj1 = {}; console.log(typeof obj1); // object对象
4.如何给对象添加属性和方法
var person1 = { name:"小明", age:20, height:180, sex:"男", walk:function(){ console.log("i can walk!") ; return 2; } } var _name1 = person1.name; console.log(_name1); // 结果为:小明 console.log(person1.walk()); // 结果为:i can walk 2 在这里需要注意:在对象中添加的内容:属性和属性值用:(冒号)隔开,属性和属性之间用;(逗号)隔开,在调用对象的属性和方法是用.(点)进行调用,尤其在
最后的一个属性后面不能加,(逗号),系统会报错
5.如何利用函数的方法给对象添加属性和方法
var person = function(_name,_age,_height,_sex){ var obj = new Object();//创建一个新的对象 obj.name = _name, obj.age = _age, obj.height = _height, obj.sex = _sex, obj.walk = function(){ console.log("i can walk"); return 2; } return obj; // 将建好的对象需做为函数的返回值返回 } var person = new person("小明",16,160,"男"); console.log(person.walk());// 输出结果:i can walk 2 person.walk();//输出结果:i can walk console.log(person.height); // 输出结果: 160
6.用够着函数的方法创建对象:注意:构造函数的首字母大写;构造函数的机制:构造函数会自动创建一个空对象,然后与this向关联,并且作为默认返回值返回
function Person(_name,_age,_height){ this.name = _name, this.age = _age, this.height = _height, this.walk = function(){ console.log("i can walk"); return 2; } } var person1 = new Person("小明",18,180); var person2 = new Person("小红",20,170); console.log(person1.name);//输出结果:小明 console.log(person2.walk());// i can walk 2 person1.walk();i can walk
注意:构造函数:通过构造函数我们就不用反复定义属性和方法,我们通过构造函数构造了两个对象:person1,person2.同时person1和person2也可以叫做够着函数Person的两个实例。
7.当然系统内置了许多的构造函数 例如:String Array Object Number:简单用代码举两个例子
var str1 = new String("123"); console.log(str1);//输出结果:String{“123”} console.log(typeof str1);//输出结果为:Object var str2 = new Number("123"); console.log(str2);//输出结果为:Number{123} console.log(typeof str2);//输出结果为:object 可见他们都是一种构造函数,创建出来的都是对象
8.原型prototype
prototype是用来解决内存被过多占用的问题,每一个函数在创建的时候都会默认的分配一个prototype属性,构造函数也不例外,同时prototype是一个指针,他指向一个对象,原型prototype的特点,在内存中只有一份
function Person(_name,_age,_height){ this.name = _name, this.age = _age, this.height = _height, this.walk = function(){ console.log("我也会走路"); } } Person.prototype.info = function(){ console.log("我的姓名是:"+this.name); } Person.prototype.walk = function(){ console.log("i can walk"); } var person = new Person("小明",18,180); console.log(person.name); //输出结果:小明 person.info();//输出结果:我的姓名是:小明 person.walk();//输出结果:我也会走路 这个时候我们将构造函数中的walk方法注释掉,之后我们在调用walk方法 person.walk();//输出结果为:i can walk 由此可知:当对象尝试调用摸个属性和方法的时候,会首先去该对象的构造函数中去找,如果在该函数的构造函数没有的话就会去,改构造函数的原型中去找
9.将原型也作为一个对象
function Person(_name,_age,_height){ this.name = _name, this.age = _age, this.height = _height this.walk = function(){ console.log("我也会走路"); } } Person.prototype = { info:function(){ console.log("我的姓名是:"+this.name); }, walk:function(){ console.log("i can walk"); } } var person = new Person("小红",18,170); console.log(person.name);//输出结果:小红 person.info();//我的姓名是:小红 person.walk();//我也会走路 和上面没有什么差别,就是换了一种创建原型的方法
10.面向对象有三大特征:封装、继承、多态、我们现在就说一下继承,在继承中有很多方法,首先说一下call和apply方法(两种方法基本是一样的)call和apply方法的根本在于改变this的指向。但是这种方式只能实现构造函数的继承,但是不能实现原型的继承
//首先创建一个构造函数 function Person(_name,_age,_sex){ this.name = _name; this.age = _age; this.sex = _sex; } //为构造函数创建原型 Person.prototype = { info:function(){ console.log("我的名字是:"+this.name); }, walk:function(){ console.log("i can walk"); } } //创建一个构造函数继承Person function Student(_name,_age,_sex,_height){ Person.call(this,_name,_age,_sex);//call方法进行继承 this.height = _height; } var student = new Student("小明",18,"男",180); var person = new Person("小红",16,"女"); console.log(student.name,student.height);//输出结果:小明 180 console.log(person.name,student.age); // 小红 18 person.info();//输出结果为: 我的名字是:小红 student.info();//输出结果为 student.info is not a function //由此可见:Student虽然继承了Person的构造函数,但是并没有继承Person的原型
11.基于之前的代码我们更改一下Student的继承方式改成apply看看有什么效果
//首先创建一个构造函数 function Person(_name,_age,_sex){ this.name = _name; this.age = _age; this.sex = _sex; } //为构造函数创建原型 Person.prototype = { info:function(){ console.log("我的名字是:"+this.name); }, walk:function(){ console.log("i can walk"); } } //创建一个构造函数继承Person function Student(_name,_age,_sex,_height){ Person.apply(this,[_name,_age,_sex]);//apply方法进行继承 this.height = _height; } var student = new Student("小明",18,"男",180); var person = new Person("小红",16,"女"); console.log(student.name,student.height);//输出结果:小明 180 console.log(person.name,student.age); // 小红 18 person.info();//输出结果为: 我的名字是:小红 student.info();//输出结果为 student.info is not a function //由此可见:Student虽然继承了Person的构造函数,但是同样并没有继承Person的原型
12.如何让student继承person的原型:在原型继承的问题上可能有人说我们直接把Person的原型赋值给Student的原型不就行了吗?那我们先来看看这个方法
//首先我们还是粘贴一下前面的代码 //创建一个构造函数 function Person(_name,_age,_sex){ this.name = _name; this.age = _age; this.sex = _sex; } //为构造函数创建原型 Person.prototype = { info:function(){ console.log("我的名字是:"+this.name); }, walk:function(){ console.log("i can walk"); } } //创建一个构造函数继承Person function Student(_name,_age,_sex,_height){ Person.apply(this,[_name,_age,_sex]);//apply方法进行继承 this.height = _height; } //将Person的原型赋值给Student的原型 Student.prototype = Person.prototype; //为了区别一下两个原型,我们在给Student原型在加一个方法 Student.prototype.high = function(){ console.log("我的身高是:" + this.height) ; } var person = new Person("小红",16,"女"); var student = new Student("小明",18,"男",180); //在这里我们只看原型的继承,构造函数的继承就不多说了 person.info();// 输出的结果:我的名字是:小红 student.info();//输出的结果:我的名字是:小明 student.high();//输出的结果:我的身高是:180 //目前可见:Student继承了Person原型,而且他自己独有的原型方法业保持了 //但是这个方法也是有很大的弊端,我们执行一下下面的代码 person.high();//输出的结果:我的身高是:undefined //这就出问题了,正常应该是person.high not a function才对,因为我们并没有在person原型里定义high方法,但是这里却显示方法存在,只是没有
//定义参数 //其实原因很简单,在之前我们说过这里的原型就像是一个指针,当我们进行赋值后,更改的是指针所指的地址,于是Student和Person的原型都发生了改变
13.那么我们如何实现原型的继承呢?在原型我们常用的方法就是讲Student的原型作为Person类的一个实例化对象
//首先我们还是粘贴一下前面的代码 //创建一个构造函数 function Person(_name,_age,_sex){ this.name = _name; this.age = _age; this.sex = _sex; } //为构造函数创建原型 Person.prototype = { info:function(){ console.log("我的名字是:"+this.name); }, walk:function(){ console.log("i can walk"); } } //创建一个构造函数继承Person function Student(_name,_age,_sex,_height){ Person.apply(this,[_name,_age,_sex]);//apply方法进行继承 this.height = _height; } //将Student的原型作为Person的一个实例化对象 Student.prototype = new Person("天天",16,"女"); //为了区别一下两个原型,我们在给Student原型在加一个方法 //原型创造函数1 Student.prototype.high = function(){ console.log("我的身高是:" + this.height) ; } //原型创造函数2 Student.prototype = { high:function(){ console.log("我的身高是:" + this.height) ; } } var person = new Person("小红",16,"女"); var student = new Student("小明",18,"男",180); //在这里我们只看原型的继承,构造函数的继承就不多说了 person.info();// 输出的结果:我的名字是:小红 student.info();//输出的结果:我的名字是:小明 student.high();//输出的结果:我的身高是:180 //目前可见:到这里是没有问题的,下面我们依旧测试一下 person.high();//输出的结果:person.high is not a function //可见这个是对的 //当然这个也是有一些其他的问题的 //在之前我们提到了两种创造原型的方式;第一种方式是没有问题的,现在我们看一下第二种(屏蔽第一种) //此时除了丝毫不影响的person.info()不受影响外;后面就会提示:student.info is not a function:这个原因是什么呢? //其实这个原因很简单,就是后面的原型把前面的去远行给覆盖掉了,所以说在进行继承后大家还想给继承者加上其他方法时就按照原型创建函数1来进行就可以了
14:原型链:当对象尝试获取某一个属性或者方法时,若该对象的构造函数没有,回到构造函数的原型函数中去找,如果原型中也没有那么就去原型对象的原型去找,最终到达Object.prototype