《原型链重置版》一万多字让你读懂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方法基本上被所有现代浏览器引擎所支持, 并且也允许动态地修改对象的原型

相关文章
|
3天前
|
编解码 JavaScript 前端开发
【Java进阶】详解JavaScript的BOM(浏览器对象模型)
总的来说,BOM提供了一种方式来与浏览器进行交互。通过BOM,你可以操作窗口、获取URL、操作历史、访问HTML文档、获取浏览器信息和屏幕信息等。虽然BOM并没有正式的标准,但大多数现代浏览器都实现了相似的功能,因此,你可以放心地在你的JavaScript代码中使用BOM。
42 23
|
5月前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
5月前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
110 1
|
5月前
|
Web App开发 JavaScript 前端开发
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
|
5月前
|
JSON 前端开发 JavaScript
JavaScript中对象的数据拷贝
本文介绍了JavaScript中对象数据拷贝的问题及解决方案。作者首先解释了对象赋值时地址共享导致的值同步变化现象,随后提供了五种解决方法:手动复制、`Object.assign`、扩展运算符、`JSON.stringify`与`JSON.parse`组合以及自定义深拷贝函数。每种方法都有其适用场景和局限性,文章最后鼓励读者关注作者以获取更多前端知识分享。
63 1
JavaScript中对象的数据拷贝
|
5月前
|
JavaScript 前端开发 图形学
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。
|
8月前
|
开发者 图形学 iOS开发
掌握Unity的跨平台部署与发布秘籍,让你的游戏作品在多个平台上大放异彩——从基础设置到高级优化,深入解析一站式游戏开发解决方案的每一个细节,带你领略高效发布流程的魅力所在
【8月更文挑战第31天】跨平台游戏开发是当今游戏产业的热点,尤其在移动设备普及的背景下更为重要。作为领先的游戏开发引擎,Unity以其卓越的跨平台支持能力脱颖而出,能够将游戏轻松部署至iOS、Android、PC、Mac、Web及游戏主机等多个平台。本文通过杂文形式探讨Unity在各平台的部署与发布策略,并提供具体实例,涵盖项目设置、性能优化、打包流程及发布前准备等关键环节,助力开发者充分利用Unity的强大功能,实现多平台游戏开发。
328 0
|
8月前
|
JavaScript 前端开发 开发者
揭开JavaScript的神秘面纱:原型链背后隐藏的继承秘密
【8月更文挑战第23天】原型链是JavaScript面向对象编程的核心特性,它使对象能继承另一个对象的属性和方法。每个对象内部都有一个[[Prototype]]属性指向其原型对象,形成链式结构。访问对象属性时,若当前对象不存在该属性,则沿原型链向上查找。
60 0
|
10月前
|
JavaScript 前端开发
JavaScript进阶-原型链与继承
【6月更文挑战第18天】JavaScript的原型链和继承是其面向对象编程的核心。每个对象都有一个指向原型的对象链,当查找属性时会沿着此链搜索。原型链可能导致污染、效率下降及构造函数与原型混淆的问题,应谨慎扩展原生原型、保持原型结构简洁并使用`Object.create`或ES6的`class`。继承方式包括原型链、构造函数、组合继承和ES6的Class继承,需避免循环引用、方法覆盖和不当的构造函数使用。通过代码示例展示了这两种继承形式,理解并有效利用这些机制能提升代码质量。
147 5
|
11月前
|
JavaScript 前端开发
深入探讨JavaScript中的原型链与继承机制
JavaScript作为一种灵活而强大的编程语言,其独特的原型链与继承机制是其核心特性之一。本文将深入探讨JavaScript中的原型链与继承机制,从基础概念到实际应用,帮助读者更好地理解和利用JavaScript的继承特性。
下一篇
oss创建bucket