一、关于类
所 “类” 谓就是对象的模板,对象就是“类”的实例,而Javascript在es6之前没有类这个概念,Javascript使用构造函数来模拟Java中的类
1-1 构造函数
定义:就是构造一个对象的函数(java—构造函数和类名相同)
function Person(name,age){
this.name=name;
this.age=age
}
/* 使用new关键字去实例化对象 */
var zhang=new Person("zhangsan",18);
console.log(zhang)
1-2 构造函数的特点
- 函数体内部使用了this关键字,代表了所要生成的对象实例。
- 生成对象的时候,必须使用new命令
- 在构造函数中 谁使用new关键字调用构造函数,this就指向谁
1-3 new命令的原理
使用new命令时,它后面的函数一次执行下面的步骤
- 创建一个对象实例
实例化对象的原型指向构造函数的原型对象
console.log(chengchao.__proto__== Person.prototype)
-
二、原型
**JavaScript的继承是基于原型的继承
JavaScript 通过构造函数生成新对象,因此构造函数可以视为对象的模板。实例对象的属性和方法,可以定义在构造函数内部。
只要在原型对象上设置一个方法,所有的对象都用有这个方法var arr=new Array(1,2,3);
Array.prototype.sayHello=function(){
console.log("hello")
}
var a=[4,5,6]
arr.push(4) //push也是写在原型上的
arr.sayHello() //在原型上添加的方法,输出:hello
a.sayHello() //hello
var Person = function(name,age){
this.name = name;
this.age = age;
}
var pengzhengang = new Person("name",18)
console.log(pengzhengang.name); //"程超"
console.log(pengzhengang.age); //18
三、原型链,继承
3-1 原型链
- JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型
- 所有对象皆有proto属性,它指向它的原型对象
3-2 继承
- 每一个对象都会有一个隐藏属性proto,它指向它的原型对象
这个对象会享有原型上的属性或者方法
<script>
/* 为什么一个实例化的对象能够使用它原型上的方法 */
function Person(name,age){
this.name=name;
this.age=age;
}
Person.prototype.sayName=function(){
console.log(this.name)
}
/*
1.每一个对象都有一个隐藏属性__proto__,它指向它的原型对象
2.这个对象会享有原型上的属性或者方法
*/
var peng=new Person("pengzhengang",18)
console.log(peng)
console.log(peng.__proto__)
console.log(peng.__proto__==Person.prototype)
</script>
如果一个对象自身没有一个方法,它就会从它的原型上去找
- object.prototype是终点,是源头 ,没有proto属性
四、ES6实现一个Class
使用extends关键字可以实现继承,之后可以自动拥有父类的属性和方法
<script>
/* 面向对象的方法
function Person(name,age){
this.name=name;
this.age=age;
}
Person.prototype.sayName=function(){
this.name;
} */
/* es6的方法 */
class Person{
constructor(name,age){
this.name=name;
this.age=age;
}
sayName(){
console.log(this.name) //lisi
}
}
/* 使用extends关键字可以实现继承,之后可以自动拥有父类的属性和方法 */
class Student extends Person{
constructor(name,age,skill){
super(name,age); //super指的是Person
this.skill=skill
}
/* //子类下的函数:这种写法是错误的
saySkill(){
console.log(this.skill)
} */
}
var zhang=new Person("zhangsan",18);
// /* 父类不能使用子类的方法,子类可以使用父类的方法 */
// zhang.saySkill()
var s=new Student("lisi",17,"html")
s.sayName()
console.log(s) //Student("lisi",17,skill:"html")
</script>
在子类的方法中去调用父类的方法—this
class Person{
constructor(name,age){
this.name=name;
this.age=age;
}
sayName(){
console.log(this.name)
}
}
/* 在子类的方法中去调用父类的方法 */
class Student extends Person{
constructor(name,age,skill){
super(name,age); //super指的是Person
this.skill=skill
}
saySkill(){
this.sayName()
}
}
var peng=new Student("lisi",17,"html")
peng.saySkill()
var p=new Person("zhangsan",18)
console.log(Person.prototype)
五、static
5-1 静态方法
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为 “静态方法”
class Father {
static testMethod() {
return 'hello';
}
}
//通过类名直接调用
Father.testMethod() // 'hello'
var Child = new Father();
Child.testMethod()
// TypeError: Child.testMethod is not a function
//这是因为Father中的testMethod方法是静态方法(有static关键字),不会被实例化出来的Child继承
5-2 静态属性和实例属性
静态属性指的是Class本身的属性,即Class.propname,而不是定义在实例对象(this)上的属性
// StaticMethod.js
// 定义静态属性
StaticMethod.firstName = 'pca';
console.log(StaticMethod.firstName);
// 定义实例属性
// ES6实例属性只能在constructor构造函数中定义
constructor() {
super();
this.width = '40cm';
}
getWidth(){
return this.width;//使用的时候需要加上this
}
// 为了可读性的目的,对于那些在constructor里面已经定义的实例属性,新写法允许直接列出。
width;
5-2 static继承
父类的静态方法可以被子类继承
class Father {
static testMethod() {
return 'hello';
}
}
class Child extends Father {
}
Child.classMethod(); // 'hello'
//上面代码中,父类Father有一个静态方法,子类Child可以调用这个方法,因为这是通过extends继承的,不是通
过new()实例化得到的