构造函数
特点:不同的是构造函数习惯上首字母大写,而构造函数需要使用new关键字来调用。
function Person(name,age,gender){
this.name = name;
this.age = age ;
this.gender = gender;
this.sayName = function(){
console.log(name);
}
}
var per = new Person("zhangsan",20,'女');
console.log(per); //{name: "zhangsan", age: 20, gender: "女", sayName: ƒ}
console.log(per.sayName()) //zhangsan;
每一个对象数据类型(普通的对象、实例、prototype…)也天生自带一个属性__proto__
原型
在javascript中,每当定义一个函数数据类型(普通函数,类),都会天生自带一个prototype属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。
function person(){
console.log("我是person")
}
console.log(person.prototype);
原型对象中有一个属性constructor, 它指向函数对象。
原型链
1.proto__和constructor
每一个对象数据类型(普通的对象、实例、prototype…)也天生自带一个属性__proto,属性值是当前实例所属类的原型(prototype)。原型对象中有一个属性constructor, 它指向函数对象。
function Person(){
console.log("我是李四");
}
var p = new Person();
console.log(p.__proto__ === Person.prototype) //true
console.log(Person.prototype.constructor === Person) //true
//顺便学习一个ES5的方法,可以获得对象的原型
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
2.何为原型链
在javascript中万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在javaScript中式通过prototype对象,直到指向对象为止,这样就形成了一个原型链,称之原型链。
function Person(){
console.log("我是Person");
}
Person.prototype.name = "张三";
Person.prototype.sayHello = function(){
console.log("Hello");
}
var p = new Person();
console.log(p.name) //张三
判断是否存在a
console.log(person.hasOwnProperty('a'));//false
console.log('a'in person)//true
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层Object为止。Object是JS中所有对象数据类型的基类(最顶层的类)在Object.prototype上没有__proto__这个属性。
console.log(Object.prototype.__proto__ === null) // true
实例与原型
当读取实例的属性时,如果找不到,就会查找与对象关联的原理中的属性,如果还查不到,就找原型的原型,一直找到最顶层为止。
function Person(){}
Person.prototype.name = 'Kevin';
var person = new Person();
person.name = 'Daisy';
console.log(person.name); //Daisy
delete person.name;
console.log(person.name); //Kevin
原型的原型
var obj = new Object();
obj.name = 'Kevin';
console.log(obj.name);
Javascript 之继承的多种实现方式和优缺点
一、 原型链继承
主要问题:
- 引用类型的属性被所有实例共享(this.children.push(‘name’))
- 在创建Child的实例的时候,不能向Parent传参
function Parent() {
this.name = 'zhangsan';
this.children = ['A', 'B', 'C'];
}
Parent.prototype.getName = function() {
console.log(this.name);
}
function Child() {
}
Child.prototype = new Parent();
var child = new Child();
console.log(child.getName());
二、借用构造函数(经典继承)
优点:
- 避免了引用类型的属性被所有实例共享
- 可以直接在Child中向Parent传参
缺点:
方法都在构造函数中定义了,每次创建实例都会创建一遍方法
function Parent(age) {
this.names = ['zhangsan', 'lisi'];
this.age = age;
this.getName = function() {
return this.names;
}
this.getAge = function() {
return this.age;
}
}
function Child(age) {
Parent.call(this, age);
}
var child = new Child(18);
child.names.push('haha');
console.log(child.names);
var child2 = new Child(20);
child2.names.push('yaya');
console.log(child2.names);
三、组合继承(原型链继承和经典继承双剑合璧)
优点: 融合了原型链继承和构造函数的优点,是Javascript中最常用的继承模式
/**
* 父类构造函数
* @param name
* @constructor
*/
function Parent(name) {
this.name = name;
this.colors = ['red', 'green', 'blue'];
}
Parent.prototype.getName = function() {
console.log(this.name);
}
// child
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = new Parent();
// 校正child的构造函数
Child.prototype.constructor = Child;
// 创建实例
var child1 = new Child('zhangsan', 18);
child1.colors.push('orange');
console.log(child1.name, child1.age, child1.colors); // zhangsan 18 (4) ["red", "green", "blue", "orange"]
var child2 = new Child('lisi', 28);
console.log(child2.name, child2.age, child2.colors); // lisi 28 (3) ["red", "green", "blue"]
具体的链接https://blog.csdn.net/m0_37981569/article/details/94204632