《原型链重置版》一万多字让你读懂JavaScript原型对象与原型链的继承,探秘属性的查找机制! (5)

简介: 更多javascript继承实现的方式

logo.png

另类继承实现方法

修改构造函数this指向从而实现继承

我们有时候可以借助call方法来实现简单的继承效果!

举个栗子

function Animal(name,age,food){
   
   
    this.username=name;
    this.age=age;
    this.eat=function (){
   
   
        console.log('这只['+this.username+']动物要吃['+food+']');
    }
}


Animal.prototype.color='黑色';
Animal.prototype.say=function (){
   
   
    console.log('我的名字叫'+this.name);
}

function Panda(name,age,eat){
   
   
    this.like='玩耍';
    Animal.call(this,name,age,eat); //借用一下
}

var p1=new Panda('熊猫盼盼',18,'竹叶');

//打印输出
console.log(p1);
p1.eat();

结果

11-0-2.png
)

这个案例中,应用了call修改this指向来达到一个共享的目的!

但是这种使用call等方法来修改this严格意义上来讲,只能算借用!

因为这种方式有一个很大的缺点,就是不能继承所谓父类原型里面的属性方法,不然你看上图,打印的结果当中并没有出现Animal类原型对象中的color属性say方法

所以这种继承方式如何和prototype修改原型方式结合一起使用就会有意想不到的效果,并且参数的传递也会更加灵活多变!

举个栗子

//定义构造函数
function Person(userename,age,sex){
   
   
    this.name=userename;
    this.age=age;
    this.sex=sex;
    this.type='人类';
}
Person.prototype.say=function(){
   
   
    console.log("hello world");
}

function Student(username,age,sex,score){
   
   
    //借用Person构造函数
    Person.call(this,username,age,sex);
    //定义属性
    this.score=score
}

//改变原型指向
Student.prototype=new Person();//不传值
Student.prototype.behavior=function(){
   
   
    console.log("英语学习!!");
}


var s1=new Student("张三",15,"男","100分")

//打印结果看看
console.log(s1);
console.log(s1.type);
console.log(s1.name);
console.log(s1.age);
console.log(s1.sex);
console.log('考试得分:'+s1.score);

s1.behavior();
s1.say();

代码分析

从上面的代码中,我们可以看到构造函数Student中我们借用了Person构造函数, 然后在通过prototype修改原型指向,这样一来,不仅可以获取到父类构造函数中的属性和方法 也可以获取到父类原型对象中的属性和方法

这时都可以通过__proto__这个链条拿到!

如图

11-0-3.png

通过循环复制实现继承

我们的原型对象prototype既然是一个对象,那么我们也可以通过循环复制的手法把父级原型对象里面的属性和方法拷贝到目标原型对象下,同时也可以结合call方法借用构造函数中的属性和方法

代码如下

function Person(username,age) {
   
   
    this.name=username;
    this.age=age;
}

Person.prototype.type = "人类";
Person.prototype.nationality = "中国";
Person.prototype.job = '软件开发';
Person.prototype.like = '足球,篮球,游戏';
Person.prototype.test = 123;


function Student(username,age) {
   
   
    Person.call(this,username,age);
}

var per = Person.prototype;
var stu = Student.prototype;


//过滤不需要的属性
var arr=['type','nationality','test'];
for (k in per) {
   
   
    if(arr.indexOf(k)==-1){
   
   
        stu[k] = per[k];
    }
}

var s1=new Student('李四',18);
var s2=new Student('王五',25);

console.log(s1);
console.log(s2);

如图

11-0-4.png

__proto__的兼容性

根据MDN官方的建议,其实__proto__是被弃用了的!

那么到底我们平常使用什么来修改原型的指针呢?

JavaScript 中,你的确是可以通过直接修改实例对象__proto__ 属性来达到目的!

__proto__ 是一个非标准的属性,它在大多数的js环境中都可以使用,包括浏览器Node.js 但是由于这个属性是非标准的,它在一些环境中可能不可用,或者在未来的标准中可能会被弃用,也就是说虽然一些浏览器仍然支持__proto__,但也许已从相关的web标准中移除,也许正准备移除或者出于兼容性而保留!

__proto__浏览器兼容性如下表

11-1.png

所以如果可以的话我们尽量不使用__proto__而改成其他,例如:Object.setPrototypeOf方法

举个栗子

让我们使用Object.setPrototypeOf来实现一个简单的继承

代码如下

function Test(){
   
   

}

Test.prototype.company='重庆科技';

function Test2(){
   
   

}

Test2.prototype.num=100;


function Test3(){
   
   

}

Test3.prototype.username='张三';

//实现继承
Object.setPrototypeOf(Test2.prototype, Test.prototype);
Object.setPrototypeOf(Test3.prototype, Test2.prototype);

var t3=new Test3();
console.log(t3);

效果

11-2.png

再看一个案例!

const a = {
   
    company : '重庆科技' };
const b = {
   
    age: 33 };
const c = {
   
    username: "张三" };

//实现继承
Object.setPrototypeOf(a, b);
Object.setPrototypeOf(b, c);

console.log(a);
console.log(a.username);
console.log(a.age);
console.log(a.company);

效果如下

11-3.png

所以我觉得可以的情况下,尽量使用标准的Object.setPrototypeOf方法来实现继承

因为Object.setPrototypeOf方法基本上被所有现代浏览器引擎所支持, 并且也允许动态地修改对象的原型

相关文章
|
8天前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
11天前
|
Web App开发 JavaScript 前端开发
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
|
6天前
|
JavaScript 安全 中间件
深入浅出Node.js中间件机制
【10月更文挑战第36天】在探索Node.js的奥秘之旅中,中间件的概念如同魔法一般,它让复杂的请求处理变得优雅而高效。本文将带你领略这一机制的魅力,从概念到实践,一步步揭示如何利用中间件简化和增强你的应用。
|
9天前
|
JavaScript 前端开发
JavaScript 原型链的实现原理是什么?
JavaScript 原型链的实现原理是通过构造函数的`prototype`属性、对象的`__proto__`属性以及属性查找机制等相互配合,构建了一个从对象到`Object.prototype`的链式结构,实现了对象之间的继承、属性共享和动态扩展等功能,为 JavaScript 的面向对象编程提供了强大的支持。
|
9天前
|
JavaScript 前端开发
原型链在 JavaScript 中的作用是什么?
原型链是 JavaScript 中实现面向对象编程的重要机制之一,它为代码的组织、复用、扩展和多态性提供了强大的支持,使得 JavaScript 能够以简洁而灵活的方式构建复杂的应用程序。深入理解和熟练运用原型链,对于提升 JavaScript 编程能力和开发高质量的应用具有重要意义。
|
10天前
|
JavaScript 前端开发
如何使用原型链继承实现 JavaScript 继承?
【10月更文挑战第22天】使用原型链继承可以实现JavaScript中的继承关系,但需要注意其共享性、查找效率以及参数传递等问题,根据具体的应用场景合理地选择和使用继承方式,以满足代码的复用性和可维护性要求。
|
11天前
|
JavaScript 前端开发 图形学
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。
|
18天前
|
消息中间件 JavaScript 中间件
深入浅出Node.js中间件机制
【10月更文挑战第24天】在Node.js的世界里,中间件如同厨房中的调料,为后端服务增添风味。本文将带你走进Node.js的中间件机制,从基础概念到实际应用,一探究竟。通过生动的比喻和直观的代码示例,我们将一起解锁中间件的奥秘,让你轻松成为后端料理高手。
22 1
|
21天前
|
JavaScript 前端开发 开发者
探索JavaScript原型链:深入理解与实战应用
【10月更文挑战第21天】探索JavaScript原型链:深入理解与实战应用
26 1
|
29天前
|
JavaScript 前端开发 开发者
深入理解JavaScript原型链:从基础到进阶
【10月更文挑战第13天】深入理解JavaScript原型链:从基础到进阶
20 0