原型上挂载的属性和方法是为所有实例化对象所共享的,可以帮我们节省内存空间。
每一个 JavaScript 对象(null 除外)在创建的时候就会与之关联一个对象,这个对象就是我们所说的原型。
可以理解为原型是在模仿类的概念。
function Person(name,age){
// 属性
this.name = name;
this.age = age;
// 方法
this.sayHello = function(){
console.log("hello");
}
}
var zhangsan = new Person("张三",20);
var lisi = new Person("李四",22);
zhangsan.sayHello(); //hello
lisi.sayHello(); //hello
// 说明每次通过new来创建新的对象的时候,都会创建一个新的sayHello方法,造成资源浪费
// 这两个对象的sayHello方法不同
console.log(zhangsan.sayHello=== lisi.sayHello);//false
Person.prototype 就是原型对象,Person.prototype.xxx 是 我们自己 对原型对象进行的 扩展,目的就是 Person 构造函数的所有实例都可以 继承 这些属性或方法。
function Person(name,age){
this.name = name;
this.age = age;
}
// 放在原型身上
Person.prototype.sayHello= function(){
console.log("hello");
}
Person.prototype.job = "it";
var zhangsan = new Person("zhansgan",30);
var lisi = new Person("lisi",25);
zhangsan.sayHello(); // hello
lisi.sayHello();// hello
console.log(zhangsan.job);; //it
console.log( lisi.job);;//it
console.log(zhangsan.sayHello === lisi.sayHello); // true
console.log(zhangsan.job === lisi.job); // true
// 原型对象的作用,就是定义所有实例对象共享的属性和方法。
function Person(){
this.job = "it"; // 自身属性
}
console.log(Person.prototype);
Person.prototype.job= "运营"; //原型属性
var p1 = new Person();
var p2 = new Person();
p2.job = "客服"; // 可单独给对象的属性赋值,来改变值
console.log(p1.job); // it
console.log(p2.job); // 客服
// 实例: 实例方法 实例属性
// 静态: 静态方法 静态属性
function Person(name,age){
this.name = name;
this.age = age;
}
// 实例方法
Person.prototype.sayHello = function(){
console.log("hello");
}
// 静态方法
Person.sayBye = function(){
console.log("byebye");
}
// 实例方法调用————实例对象来调用
var p = new Person("zhangsan",20);
p.sayHello(); // hello
// 静态方法调用————类名.方法名 调用
Person.sayBye(); //byebye
function Person(name){
this.name = name;
}
// 实例属性
Person.prototype.hello = "hello";
// 静态属性
Person.bye = "bye";
// 实例属性调用 实例对象.属性
var P = new Person();
console.log( P.hello); // hello
// 静态属性调用 类名.属性
console.log(Person.bye); // bye
注:该属性只有浏览器环境下有,其他环境下没有这个属性。
function Person(){}
// 实例化对象
var p = new Person();
// 通过类名获取原型
console.log(Person.prototype); // 以前是这样获得原型的
// 通过实例对象P来获得原型,这里的每个下划线都是两个_
console.log(p.__proto__); // 对象的原型
console.log(Person.prototype === p.__proto__); // true
constructor属性作用:当构造函数外部访问不到时,可以通过实例化对象在原型上继续扩展属性和方法,添加完成后可继续被其他实例化对象共享
function Person(name){
this.name = name;
}
var zs = new Person("zhangsan");
// 实例化对象的构造函数:就是Person函数
console.log(Person); // Person的函数体
console.log(zs.constructor === Person); // true
console.log(Person.prototype.constructor === zs.constructor); // true
instanceof 运算符 返回一个布尔值,表示对象是否为某个构造函数的实例化对象,instanceof会检查整个原型链
function Person(){}
var p = new Person();
console.log(p instanceof Person); //true: p是Person的实例对象
console.log(p instanceof Object); //true // instanceof会检测整个原型链
Object.getPrototypeOf(实例化对象名称):
获取实例对象的原型对象的标准方法
function Person(){ }
Person.prototype.getName= function(){}
var zs = new Person();
// 获取原型对象的三种方法
console.log(Object.getPrototypeOf(zs)); // 方法一
console.log(Person.prototype); // 方法二-通过类名获取原型
console.log(zs.__proto__);// 方法三-只有浏览器可用【不推荐】
console.log(Person.prototype === zs.__proto__); // true
console.log(Object.getPrototypeOf(zs) === Person.prototype); // true
Object.create() 方法
: es5继承,让一个对象继承另一个对象的属性和方法。
在原型上添加或修改任何方法,会立刻反映在新对象之上。
方法还可接受第二个参数。该参数是一个属性描述对象,它所描述的对象属性,会添加到实例对象,作为该实例对象自身的属性。
function Parent(){
// 属性
this.name = '张三';
}
function Son(){
// 属性继承,此处this的指向是Son的实例化对象
// apply将Parent类中的this指向变成了Son的实例化对象,所以Son类继承了Person的属性
Parent.apply(this);
}
Parent.prototype.getName = function(){
console.log("111");
}
// 子类继承父类Object.create()
Son.prototype = Object.create(Parent.prototype);
var s = new Son(); // 子类的实例化对象
s.getName(); // 111
console.log(s.name); // 张三
var animal = {
cat:"猫",
dog:{
value:"狗"
}
}
// create第二个属性必须是一个对象类型
var zoo = Object.create(animal,{
pig:{
value:"猪"
}
});
console.log(zoo.cat); // 猫
console.log(zoo.pig); // 猪
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.getName = function(){
console.log(this.name);
}
Person.prototype.getAge = function(){
console.log(this.age);
}
function Student(name,age,learn){
// 继承属性
Person.call(this,name,age); // Person中的this指向变成了student,name/age为Person中传的参数
this.learn = learn;
}
// 继承--------------------------------------------------
// 【本程序重点】继承父类方法
for(var p in Person.prototype){
Student.prototype[p] = Person.prototype[p];
}
// -------------------------------------------------------
// 给学生添加自己的原型方法
Student.prototype.getLearn = function(){
console.log("学习");
}
// 就近原则:自己身上有用自己的,自己身上没有用继承的
Student.prototype.getName = function(){
console.log("姓名:"+this.name);
}
var student = new Student("zs",19);
student.getAge(); // 19
student.getName(); // zs
student.getLearn(); // 学习
function Eat(){
// 属性
this.eat = "吃猫粮";
}
// 实例方法
Eat.prototype.getEat = function(){
console.log('小猫吃猫粮');
}
function Voice(){
// 属性
this.voice = "喵喵喵";
}
// 实例方法
Voice.prototype.getVoice = function(){
console.log('小猫喵喵喵');
}
function Cat(name){
// apply改变this指向,完成属性继承
Eat.apply(this);
Voice.apply(this);
// name参数是Cat类自身的属性
this.name = name;
}
// 多重继承------------------------------------------
// Cat继承Eat类和Voice类
// Object.create() Cat先继承Eat类
Cat.prototype = Object.create(Eat.prototype);
// Object.assign() 继承Eat类后的Cat类与Voice类合并
Object.assign(Cat.prototype,Voice.prototype);
// 完成继承后Cat类的原型对象少一个构造方法,加上
Cat.prototype.constructor = Cat;
// ----------------------------------------------------------
console.log(Cat.prototype);
// 给Cat添加自身的实例方法
Cat.prototype.getName = function(){
console.log('花花花');
}
// 实例化对象
var hh = new Cat('花花');
hh.getEat(); // 小猫吃猫粮
console.log(hh.eat); // 吃猫粮
hh.getVoice(); // 小猫喵喵喵
console.log(hh.voice); // 喵喵喵
hh.getName(); // 花花花
console.log(hh.name); // 花花