javaScript:原型、原型链、继承

原型与原型链

原型是一个从其他对象继承属性的对象。对象都是通过函数来创建的,而函数又是一种对象。

关于原型要记住三点:
(1)每个构造函数 Fn 都有一个显式原型对象 Fn.prototype, 每个原型对象都有一个指向构造函数 Fn 的指针 constructor 。

(2)由构造函数创建出来的每个实例都有一个指向原型对象的内部指针。

(3)原型对象上的属性和方法都能被它的实例访问到。
在这里插入图片描述
顺着原型找原型的原型,最后可以发现形成了一条有方向的线条,这就是原型链了。

原型链的最顶端为Object.prototype, 但 ({}).prototype是获取不到它的原型的,ECMA 5介绍了标准的访问方法是Object.getPrototypeOf({})。

Object.prototype.__proto__ = null
在这里插入图片描述

继承

继承:一个类型(子类)的实例能够访问另外一个类型(父类)的属性和方法。
1. 原型继承
核心:让一个类型(子类)的原型对象等于另一个类型(父类)的实例。

function Peron(){
}

Person.prototype.name = "john";
Person.prototype.age = 20;
Person.prototype.sayHello = function(){
	console.log(this.name);
};

function  Male(){
}

//  // test1 : 直接赋值
// Male.prototype = Person.prototype;  // 地址共用,修改子类原型,父类也被修改,x
// Male.prototype.sexy = "男";
// console.log(Person.prototype); 

//  // test2 :拷贝赋值
// for (var i in Person.prototype){		// 遍历
//  	Male.prototype[i] = Person.prototype[i];	// 拷贝赋值
// }
// Male.prototype.sexy = "男";
// console.log(Person.prototype);  // 不会修改父类原型

// test 3 : 将父类的实例赋值给子类原型
Male.prototype = new Person();
Male.prototype.sexy = "男";
var male = new Male();
male.sayHello();		// john
var person = new Person();
console.log(person.sexy);  // undefined

2. 构造函数继承
核心:使用call实现函数复用(call接受参数列表),并改变子类实例的this指向。
优点:可以传参,添加自己的属性和方法时不会修改父类
缺点:方法都在构造函数中定义,函数无法复用

 function Person(name,age){
	this.name = name;
	this.age = age;
	this.sayHello = function(){
		console.log(this.name);
	}
 }

function Male(name,age){
	Person.call(this,name,age);
	this.sexy = "男";
}

function Female(name,age){
	Person.call(this,name);
}

3. 组合继承
核心:在子类构造函数中通过parent.call(this,value)继承父类的属性,然后改变子类的原型为new Parent()来继承父类的函数。
优点:构造函数可以传参,不会与父类引用属性共享,可复用父类函数。
缺点:继承父类时调用了父类构造函数,导致子类原型上多了一些可能不需要的父类属性/方法。

 function Person(name,age){
	this.name = name;
	this.age = age;
 }
Person.prototype.sayHello = function(){
	console.log(this.name);
}

function Male(name,age){
	Person.call(this,name,age);
}
Male.prototype = new Person();
Male.prototype.sexy = "男";

var male = new Male("john",20);
male.sayHello();
console.log(Male.prototype,Person.prototype); 

4. 寄生式组合继承
核心:Object.create(obj) : 创建一个新的对象并把它与()中的参数 obj 相关联。这样,新对象本身并没有得到指定对象的任何值的副本(不会共用地址),只是将它与指定对象关联,而obj会作为新创建出来的对象的原型对象。
(1)通过call实现实例属性的继承
(2)将父类原型赋值给子类,并设置子类原型上的指针指向子类的构造函数

优点:既解决了无用父类属性的问题,还能正确的找到子类的构造函数

// 这里是Object.create()的模拟实现
function cloneObject(obj){
  function F(){}
  F.prototype = obj; // 将被继承的对象作为空函数的prototype
  return new F(); // 返回new期间创建的新对象,此对象的原型为被继承的对象, 通过原型链查找可以拿到被继承对象的属性
}
function Person(name,age){
	this.name = name;
	thia.age = age;
}
Person.prototype.sayHello = function(){
	console.log(this.name);
}

function Male(name,age){
	Person.call(this,name,age); // 实现实例属性的继承
}
 	console.log(Male.prototype); // Object {constructor: ƒ Male(name, age),__proto__: Object}
 	// 将父类原型赋值给子类,并设置子类原型上的指针指向子类的构造函数
    Male.prototype = Object.create(Person.prototype);
    console.log(Male.prototype); // Person {} {constructor: ƒ Male(name, age),__proto__: Object}

   	console.log(Male.prototype.constructor); // ƒ Person(name, age) {this.name = name;this.age = age;}
    Male.prototype.constructor = Male; 

    var male = new Male('john', 21);
    male.sayHello(); // john

	console.log(male.__proto__.constructor); // ƒ Male(name, age) {Person.call(this, name, age);}

5. ES6继承
js中并不存在类,class的本质是函数。
核心:使用extends 表明继承自哪个父类,在子类构造函数中必须调用super,可以看成是Parent.call(this,arg1,arg2,…)
(1) 每个class内部都有一个constructor,为指向构造函数的指针。
(2) constructor内部使用super,创建并改变this对象,super指向父类的构造函数。

class Person{
	constructor(name,age){
		this.name = name;
		this.age = age;
	}
	sayHello(){
		console.log(this.name);
	}
	static foo(){		// 静态方法
		console.log("aa");
	}
}

class Male extends Person{
	constructor(name,age){
		super(name,age);    // super指向父类的构造函数
		this.sexy = "男";	// this指向实例对象
	}
	sayHi(){
		super.sayHello();   // 指向父类的原型对象
	}
	static bar(){
		super.foo();		// 指向父类
	}
}

var male = new Male("john",20);
male.sayHi();   // john
Person.foo();	// aa
Male.bar();		// aa

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值