JS原型对象
一,构造函数,原型对象,实例的关系:
1,构造函数实例:封装的函数,如果通过new操作符来调用的,就是构造函数,如果没有通过new操作符来调用的,就是普通函数 2,函数Person(对象)有个属性prototype(指针)指向原型对象。 Person.prototype(原型对象,实质也是对象),他有个属性constructor(指针) ,又指向 Person函数对象
console.log(Person === Person.prototype.constructor); //true
3,实例对象person1有个属性[prototype](内部属性,chrome和firefix,Safari,中这个属性叫_proto_)指向原型对象。实例对象可以通过这个属性访问原型对象上的属性和方法(Perons.prototype.proto == person1.proto)。
function Person(name, age) {
this.name = name;
this.age = age;
}
//在原型对象中添加属性或者方法
Person.prototype.sex = '男';
var person1 = new Person('Mike',10);
var person2 = new Person('Alice',20);
//只给person2设置性别
person2.sex = '女';
console.log(person1.sex) // '男'
console.log(person2.sex) //'女'
4,可以通过实例对象(person1)的constructor(person1.constructor)访问构造函数,但是constructor本质上是原型对象的属性。
二,继承:
1,继承的主要思路是利用原型链,而原型链的原理是:让一个引用类型继承另一个引用类型的属性和方法。即原型对象通过constructor指向构造函数,实例对象通过_ptoto_指向原型对象。
function A() {}
//在A的原型上绑定sayA()方法
A.prototype.sayA = function(){
console.log("from A")
}
function B(){}
//让B的原型对象指向A的一个实例
B.prototype = new A();
//在B的原型上绑定sayB()方法
B.prototype.sayB = function(){
console.log("from B")
}
//生成一个B的实例
var a1 = new A();
var b1 = new B();
//b1可以调用sayB和sayA
b1.sayB();//'from B'
b1.sayA();//'from A'
说明:2-1,最后我们调用了b1的sayB方法,可以执行,为什么?
因为b1有[Prototype]属性可以访问B prototype里面的方法;
2-2,我们调用了b1的sayA方法,可以执行,为什么?
因为b1沿着[Prototype]属性可以访问B prototype,B prototype继续沿着[Prototype]属性访问A prototype,最终在A.prototype上找到了sayA()方法,所以可以执行
3,JavaScript语言的传统方法是通过构造函数,定义并生成新对象,prototype 属性使您有能力向对象添加属性和方法。下面是通过传统的方式创建和使用对象的案例:
//Person.js文件
function Person(x,y){ this.x = x; this.y = y; }
Person.prototype.name = 'sky'; //原型对象上的属性
Person.prototype.toString = function (){ //原型对象上的方法
return (this.x + "的年龄是" +this.y+"岁");
}
export {Person};
//index.js文件
import {Person} from './Person';
let person = new Person('张三',12);
console.log(person.toString());
4, 代码中,对象p的的name属性为私有变量,使用p.name不能直接访问
5,以上代码ES6 类class写法:
//Person.js
class Person{
// 构造
constructor(x,y){ //构造方法
this.x = x;
this.y = y;
} //方法之间不需要逗号分隔,加了会报错
toString(){ //原型对象上的方法
return (this.x + "的年龄是" +this.y+"岁");
}
}
export {Person};
//index.js
import {Person} from './Person';
let person = new Person('张三',12);
console.log(person.toString());
constructor方法是类的构造函数是默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个默认的constructor方法会被添加。所以即使你没有添加构造函数,也是有默认的构造函数的。一般constructor方法默认返回实例对象this。类的方法内部如果含有this,它默认指向类的实例。。(个人理解:
Person.prototype = this = person1
Person.prototype.constructor = Person,
person1.constructor == Person
person1.__proto__ === person1.constructor.prototype)
6,下面 这个类的名字是Expression而不是Expre,Expre只在Class的内部代码可用,指代当前类。
const Expression = class Expre{
static getAge(){
return '12';
}
getClassName(){
return " ClassName1= " +Expre.name + " ClassName2= " +Expression.name;
}
};
let exp = new Expression();
console.log(exp.getClassName());//ClassName1= Expre ClassName2= Expre
console.log(Expression.getAge());