使用构造函数创建一个实例
<script> function Person(age, name) { this.age = age this.name = name this.sing = function () { console.log("我会唱歌") } } const student = new Person(22, "张三") console.log(student) console.log(Person.age) console.log(student.age) Person.sex = "女" console.log(Person.sex) console.log(student.sex) </script>
构造函数中有实例成员和静态成员
实例成员是通过内部this添加的,如此例中的age,name,sing;它们只能通过实例对象访问,不能通过构造函数访问
console.log(Person.age)//undefined console.log(student.age)//22
静态成员是直接在函数本身上添加的,只能通过构造函数访问,不能通过实例对象访问
console.log(Person.sex)//女 console.log(student.sex)//undefined
prototype
每一个构造函数都有一个prototype属性,这是一个指针,指向原型对象,我们可以把方法直接定义在prototype对象上,这样所有的实例都可以共享这个方法
原型对象默认拥有一个 constructor 属性,指向它的构造函数
<script> /*Person 构造函数*/ function Person(name, age) { this.name = name; this.age = age; } /*构造函数的原型上添加方法*/ Person.prototype.sayHello = function () { console.log(`大家好,我是${this.name}今年${this.age}岁了`); }; /*构造函数的原型上添加方法*/ Person.prototype.study = function () { console.log(`我${this.name}要学习了`); }; let p1 = new Person("小明", 23); // p1为 构造函数Person new出来的实例对象 /*实例对象上的属性会屏蔽(遮蔽)原型上同名的属性*/ p1.study = function () { console.log(`我${this.name}正在学习web前端开发课程`); }; </script>
原型对象默认拥有一个 constructor 属性,指向它的构造函数
console.log(Person.prototype.constructor === Person); // true
每个对象实例
都有一个隐藏的属性__proto__
,被称为隐式原型
,指向它的构造函数的原型
console.log(p1.__proto__ === Person.prototype); // true
对象实例可以共享原型上面的所有属性和方法
p1.sayHello(); // 大家好,我是小明今年23岁了
实例自身的属性会屏蔽(遮蔽)
原型上同名的属性,实例上没有的属性就会去原型上去找
p1.study(); // 我小明正在学习web前端开发课程
原型链
- JavaScript 中所有的对象都是由它的原型对象继承而来。
- 而原型对象自身也是一个对象,它也有自己的原型对象,这样层层上溯,就形成了一个类似链表的结构,这就是原型链
以下代码的原型链结构图:
<script> /*Person 构造函数*/ function Person(name, age) { this.name = name; this.age = age; } /*构造函数的原型上添加方法*/ Person.prototype.sayHello = function () { console.log(`大家好,我是${this.name}今年${this.age}岁了`); }; /*构造函数的原型上添加方法*/ Person.prototype.study = function () { console.log(`我${this.name}要学习了`); }; let p1 = new Person("小明", 23); // p1为 构造函数Person new出来的实例对象 /*实例对象上的属性会屏蔽(遮蔽)原型上同名的属性*/ p1.study = function () { console.log(`我${this.name}正在学习web前端开发课程`); }; console.log(p1.__proto__ === Person.prototype); //true console.log(Person.prototype.constructor === Person); //true console.log(Person.prototype.__proto__ === Object.prototype); //true console.log(Object.prototype.constructor === Object); //true console.log(Object.prototype.__proto__); //null </script>
所有原型链的终点都是 Object.prototype
Objec.prototype
指向的原型对象同样拥有原型Object.prototype.__proto__,不过它的原型是 null
,而 null
则没有原型
原型链的查找
- 当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果这个对象本身没有这个属性时,它就会去他的
__proto__隐式原型
上去找(即它的构造函数的 prototype)。 - 如果还找不到,就去原型的原型(
即构造函数的prototype的__proto__
)上去找,....一直找到最顶层(Object.prototype
)为止。 - 如果还没有找到,则返回 undefined。
<script> Object.prototype.sayHello = function () { console.log(`大家好,我是${this.name}`); }; class People { constructor(name, age) { this.name = name; this.age = age; } eat() { console.log(`${this.name}正在吃饭`); } } //Student类继承People类 class Student extends People { constructor(name, age, id) { super(name, age); this.id = id; } eat() { console.log(`${this.name}正在吃肉肉`); } study() { console.log(`${this.name}正在学习`); } } const s1 = new Student("小明", 15, "0001"); s1.run = function () { console.log(`${this.name}每天都要跑步`); }; s1.run(); //小明每天都要跑步 自身找到,以自身为主 s1.study(); //小明正在学习 自身没有,沿原型链查找,在Student.prototype中找到 s1.eat(); //小明正在吃肉肉 自身没有,沿原型链查找,在Student.prototype中找到,就不再向上找了。 s1.sayHello(); //大家好,我是小明 自身没有,沿原型链查找,在Object.prototype中找到 </script>
重写原型带来的问题
- 在已经创建了实例的情况下重写原型,会切断现有实例与新原型之间的联系
- 如果要重写原型,一定要在重写原型后,再创建实例。
<script> function Person(name) { this.name = name; } let p1 = new Person("小明"); Person.prototype.eat = function () { console.log(`${this.name}在吃饭`); }; // 重写原型 Person.prototype = { name: "小明", sayHello() { console.log(`大家好,我是${this.name}`); }, }; p1.eat(); // 小明在吃饭 p1.sayHello(); // p1.sayHello is not a function </script>
在这个例子中,Person 的实例在重写原型对象之前创建的,在调用 p1.eat()时会输入正确的信息。
但是在调用 p1.sayHello 时候,会报错。是因为 p1 指向的原型还是最初的原型,而这个最初的原型上并没有 sayHello 这个方法,而且 eat 这个方法。
重写原型对象时,单独指定 constructor
<script> function Person() {} //重写原型,在prototype中需要重新指定constructor的值 Person.prototype = { constructor: Person, }; console.log(Person.prototype.constructor === Person); //true </script>
标签:console,log,Person,理解,原型,prototype,name From: https://www.cnblogs.com/qianduan-Wu/p/16603025.html