原型、原型链、继承
作用
数据共享,节省内存空间
案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
function Person(name,age) {
this.name=name;
this.age=age;
}
//通过原型来添加方法,解决数据共享,节省内存空间
Person.prototype.eat=function () {
console.log("吃凉菜");
};
var p1=new Person("小明",20);
var p2=new Person("小红",30);
console.log(p1.eat==p2.eat);//true
console.dir(p1);
console.dir(p2);
//实例对象中根本没有eat方法,但是能够使用,这是为什么?
</script>
</head>
<body>
</body>
</html>
通过原型的方式修改标签样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
div {
width: 300px;
height: 200px;
background-color: red;
}
</style>
</head>
<body>
<input type="button" value="显示效果" id="btn"/>
<div id="dv"></div>
<script src="common.js"></script>
<script>
function ChangeStyle(btnObj, dvObj, json) {
// this代指当前对象
this.btnObj = btnObj;
this.dvObj = dvObj;
this.json = json;
}
ChangeStyle.prototype.init = function () {
//点击按钮,改变div多个样式属性值
// this代指当前对象
var that = this;
this.btnObj.onclick = function () {//按钮
console.log(this) // this:代指 this.btnObj
for (var key in that.json) {
that.dvObj.style[key] = that.json[key];
}
};
};
var json = {"width": "500px", "height": "800px", "backgroundColor": "blue", "opacity": "0.2"};
var cs = new ChangeStyle(my$("btn"), my$("dv"), json);
cs.init();//调用方法
//点击p标签,设置div的样式
</script>
</body>
</html>
简单原型的案例
需要手动修改构造器的指向
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
function Student(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
//简单的原型写法
Student.prototype = {
//手动修改构造器的指向
constructor:Student,
height: "188",
weight: "55kg",
study: function () {
console.log("学习好开心啊");
},
eat: function () {
console.log("我要吃好吃的");
}
};
var stu=new Student("段飞",20,"男");
stu.eat();
stu.study();
console.dir(Student);
console.dir(stu);
</script>
</head>
<body>
</body>
</html>
构造函数,原型,实例对象三者间的关系
构造函数
构造函数中有一个属性叫prototype,是构造函数的原型对象
构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数
原型
实例对象的原型对象(
__proto__)指向的是该构造函数的原型对象
实例对象
构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的
实例对象属性方法的调用顺序
先在构造函数中找
构造函数中没有,调用原型中的属性和方法、
圆形中没有则报错
改变原型的指向(原型链)
原型指向可以改变 实例对象的原型
__proto__指向的是该对象所在的构造函数的原型对象构造函数的原型对象(prototype)指向如果改变了,实例对象的原型(__proto__)指向也会发生改变原型的指向是可以改变的 实例对象和原型对象之间的关系是通过
__proto__原型来联系起来的,这个关系就是原型链
//人的构造函数
function Person(age) {
this.age=10;
}
//人的原型对象方法
Person.prototype.eat=function () {
console.log("人的吃");
};
//学生的构造函数
function Student() {
}
Student.prototype.sayHi=function () {
console.log("嗨,小苏你好帅哦");
};
//学生的原型,指向了一个人的实例对象
Student.prototype=new Person(10);
var stu=new Student();
stu.eat();
stu.sayHi();
实例对象和原型对象中属性重名的问题
实例对象访问这个属性,应该先从实例对象中找,找到了就直接用
找不到就去指向的原型对象中找,找到了就使用
function Person(age,sex) {
this.age=age;
this.sex=sex;
}
Person.prototype.sex="女";
var per=new Person(10,"男");
console.log(per.sex); // 男
Person.prototype.sex="哦唛嘎的"; // 改变原型中的sex值
per.sex="人"; // 改变对象中sex的值
console.dir(per);
继承
通过原型实现继承
在构造函数的原型中添加要继承的对象,即可使用继承的方法
Student.prototype=new Person("小明",10,"男");注:因为改变原型指向的同时实现继承,直接初始化了属性,继承过来的属性的值都是一样的了
只能调用对象的属性,重新赋值,才能改变初始化的数据
这种赋值方式很不方便
function Person(name,age,sex) {
this.name=name;
this.sex=sex;
this.age=age;
}
Person.prototype.eat=function () {
console.log("人可以吃东西");
};
Person.prototype.sleep=function () {
console.log("人在睡觉");
};
Person.prototype.play=function () {
console.log("生活就是不一样的玩法而已");
};
function Student(score) {
this.score=score;
}
//改变学生的原型的指向即可==========>学生和人已经发生关系
// Student.prototype=new Person("小明",10,"男"); // 所有继承的都会有初始值
Student.prototype=new Person(); // 只继承属性,不赋初始值
Student.prototype.study=function () {
console.log("学习很累很累的哦.");
};
//相同的代码太多,造成了代码的冗余(重复的代码)
var stu=new Student(100);
console.log(stu.name);
console.log(stu.age);
console.log(stu.sex);
stu.eat();
stu.play();
stu.sleep();
console.log("下面的是学生对象中自己有的");
console.log(stu.score);
stu.study();
借用构造函数继承
借用构造函数:构造函数名字.call(当前对象,属性,属性,属性....);
解决了属性继承,并且值不重复的问题
缺陷:
父级类别中的方法不能继承
function Person(name, age, sex, weight) {
this.name = name;
this.age = age;
this.sex = sex;
this.weight = weight;
}
Person.prototype.sayHi = function () {
console.log("您好");
};
function Student(name,age,sex,weight,score) {
//借用构造函数
// >> 会引用Person中的内容
// >> 一般来说,this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向。
Person.call(this,name,age,sex,weight);
this.score = score;
}
var stu1 = new Student("小明",10,"男","10kg","100");
console.log(stu1.name, stu1.age, stu1.sex, stu1.weight, stu1.score);
var stu2 = new Student("小红",20,"女","20kg","120");
console.log(stu2.name, stu2.age, stu2.sex, stu2.weight, stu2.score);
var stu3 = new Student("小丽",30,"妖","30kg","130");
console.log(stu3.name, stu3.age, stu3.sex, stu3.weight, stu3.score);
组合继承
原型继承 + 借用用构造函数继承
//原型实现继承
//借用构造函数实现继承
//组合继承:原型继承+借用构造函数继承
function Person(name,age,sex) {
this.name=name;
this.age=age;
this.sex=sex;
}
Person.prototype.sayHi=function () {
console.log("阿涅哈斯诶呦");
};
function Student(name,age,sex,score) {
//借用构造函数:属性值重复的问题
// >> 解决原型继承中:继承过来的属性值一样的问题
Person.call(this,name,age,sex);
this.score=score;
}
//改变原型指向----继承
Student.prototype=new Person();//不传值,解决借用用构造函数继承中:父类级别的方法不能继承的问题
Student.prototype.eat=function () {
console.log("吃东西");
};
保存redis相关笔记

浙公网安备 33010602011771号