一、function构造函数
- 构造函数
function People(name) {
this.name = name
}
People.prototype.toSay= function () {
alert("我的名字是:" + this.name)
}
People.prototype.toEat= function () {
alert("我吃饭")
}
var p = new People("小明")
p.toSay(); // 我的名字是小明
在js中,函数本身也是一个对象,这种对象比较特殊,它有一个prototype属性,成为对象原型,它本质也是一个对象,包含constructor和其他属性,constructor默认指向自身构造函数。
- new一个实例对象
var p1 = new People("小明")
p1.__proto__ = People.prototype
var obj = new fn()
的过程是:
①产生一个空对象;
②this = 这个空对象;
③this.proto = fn.prototype;
④执行fn.call(this,x,y,z.....)
⑤return ④ 的结果;
实例对象是没有prototype属性!!!
- js中,怎么实现对象的继承?
- 通过原型链和构造函数的组合
//创建父构造函数
function Person(name,age){
this.name = name
this.age = age
}
// 设置父构造函数的原型对象
Person.prototype = {
constructor: Person,
showAge: function(){
console.log(this.age)
}
}
// 创建子构造函数
function Student(name,score){
Person.call(this,name) // 使用call借用Person的构造函数
this.genden = '女'
this.score = score
}
var f =function(){}
f.prototype = Person.prototype
Student.prototype = new f() //这三句实现了 Student实例.__proto__ = Person.prototype,就实现了继承
Student.prototype.showScore = function(){
console.log(this.score)
} //子类的prototype一定要在继承后面再添加!!!!
var h = new Student('hh',100)
可以看出,继承的子类的
__proto__
有两级,第一级是父类的__proto__
;第二极就是共用的Object的__proto__
;但是在任何浏览器中最好都不要去直接操作__proto__
;总结继承:
①子类中一定要写
父类.call(this,....要传的参数)
;②
var f = function(){}
f.prototype = 父类.prototype
子类.prototype = new f()
这三句实现了继承,相当于子类.prototype.__proto__ = 父类.prototype
;③往子类的prototype里添加属性一定要放在继承这步的后面!!!!!
但是缺点是父对象和子对象间还存在共享问题;即拷贝过来的属性为引用类型时,修改属性,父子对象都会受到影响
二、class类
- 通过class关键字,定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
上面代码定义了一个类,可以看到里面有一个constructor方法,这个就是构造方法,this代表的是实例对象。另外,方法之间不需要逗号分隔,加了会报错。
- ES6的类,可以看做构造函数的另一种写法
class Point {
// ...
}
typeof Point // "function"
Point === Point.prototype.constructor // true
使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。
-
构造函数的prototype属性,在类上继续存在
事实上,类的所有方法都定义在类的prototype属性上面。
class Point {
constructor() {
// ...
}
toString() {
// ...
}
toValue() {
// ...
}
}
// 等同于
Point.prototype = {
constructor() {},
toString() {},
toValue() {},
};
在类的实例上面调用方法,其实就是调用原型上的方法。
class B {}
let b = new B();
b.constructor === B.prototype.constructor // true
- class的继承 extends
class Person{
constructor(name,age){
this.name = name
this.age = age
}
showAge(){
console.log(this.age)
}
}
class Student extends Person{
constructor(name,age,score){
super(name,age) //调用父类
this.genden = '女'
this.score = score
}
shoeScore(){
console.log(this.score)
}
}
var h = new Student('hh',20,100)
总结:
①写上
extends
;②
constructor(父类和子类要传的参数){}
中一定调用super(父类的参数)
;③原型上的属性直接就在
class
里添加;