<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!-- <script>
function student(name,age){
this.name=name;
this.age=age;
this.school=function(){
console.log('hhh');
}
}
var stu1=new student('yy',22);
var stu2=new student('xx',28);
console.log(stu1);
console.log(stu2);
console.log(stu1==stu2);
</script> -->
<!-- 把不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法 -->
<!-- <script>
function student(name,age){
this.name=name;
this.age=age;
}
student.prototype.school=function(){
console.log('fndkjfn');
}
var stu1=new student('yy',22);
var stu2=new student('xx',28);
console.log(stu1);
console.log(stu2);
console.log(stu1==stu2);
</script> -->
<!-- 为什么要使用原型 -->
<script>
// 字面量创建对象
const person = {
name: "zyx",
age: 22,
hobby: 'balance'
}
// 如果想创建很多个对象,就是把上边的代码copy很多遍,显然这种做法,有很大工作量
// 解决以上存在问题,使用工厂函数
function createPerson(name, age) {
const obj = {};
obj.name = name;
obj.age = age;
return obj;
}
const person1 = createPerson('ls', 24);
const person2 = createPerson('zs', 24);
console.log(person1);
console.log(person2);
// 可以看到需要创建多个对象的话,只需要调用工厂函数createPerson即可
// 但是这个工厂函数也存在问题,就是不能判断出这个对象的类型,即不知道这个对象属于哪个工厂
// 引入构造函数,并没有专门的函数叫构造函数,而构造函数总是和new关键字一起使用
// 对上边工厂函数进行改造
function CreatePerson(name,age){
this.name=name;
this.age=age;
}
const person3 = new CreatePerson('ls', 24);
const person4 = new CreatePerson('zs', 24);
console.log(person3);
console.log(person4);
// 总结改造后的工厂函数-》构造函数
/*
1.我们将函数名的首字母大写了,在js中有个规定如果你以后打算将一个函数作为构造函数去使用那么最好把它的函数名首字母大写,来提醒使用者这是一个构造函数。其实不大写也不会有什么语法错误。
2.取消了在函数内部显示的声明一个对象“const obj = {}”,并一并取消了最后返回这个对象的操作"return obj";
3.在调用这个这个CreatePerson函数时在前面加上了new关键字
*/
// 通过查看控制台打印发现,可以知道对象属于哪个工厂了
/*
构造函数后台操作
1.在内存中创建一个新的对象。
2.让新对象的内部特性[[Prototype]]保存函数CreatePerson的prototype的属性值
3.把函数内部的this指向这个新创建的对象。
4.执行函数内部的代码
5.如果函数本身没有返回对象,那么就把这个新对象返回
*/
// 综上来看构造函数很完美了吗
// 如果想要再加一个方法呢
function CreatePerson(name, age, hobby) {
this.name = name;
this.age = age;
this.hobby = hobby;
// 添加一个方法
this.sayHi = function() {
console.log("你好,我叫" + this.name)
}
}
const person6 = new CreatePerson("zs", 23, "法外狂徒");
const person7 = new CreatePerson("lm", 26, "韩梅梅");
console.log(person6);
console.log(person7);
// 这样一来每个实例都会创建一个sayHi方法,但是并不想这样,只是想让有一个sayHi方法,然后每个实例共享就行
// 于是引出了原型,把公共方法添加到原型上
// 原型初步理解,把实例对象上需要用到的共有方法添加到原型上
// 改造构造函数
function CreatePerson(name,age){
this.name=name;
this.age=age;
}
const person10 = new CreatePerson("zs", 23, "法外狂徒");
const person11 = new CreatePerson("lm", 26, "韩梅梅");
CreatePerson.prototype.sayHi = function() {
console.log("你好,我叫" + this.name)
};
person10.sayHi();
person11.sayHi();
console.log(person11.sayHi === person10.sayHi);
/* 补充
每一个函数在创建的时候内部都会有一个prototype属性指向它的原型.但是有一个函数是个特例他就是Function.prototype.
每当我们使用new关键字创建一个实例的时候,实例的内部特性[[Prototype]]就指向了他的构造函数对应的原型
*/
/* 原型链
当我们在一个对象上查找一个属性的时候,会先在对象的本身去查找,然后如果没有找到,就会去他的原型上查找,如果这个原型也没有,而原型又可以看作一个实例对象(一般是Object()的实例对象),那么他也拥有原型,那么就会去原型的原型查找,这样一路向上查找,直到找到原型链的顶端null,还是没有找到的话就会返回undefined,这样就形成了原型链。
*/
</script>
</body>
</html>
参考博客:添加链接描述