《原型链重置版》一万多字让你读懂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 前端开发
JS将两个数组和合并成数组包对象格式的方法
JS将两个数组和合并成数组包对象格式的方法
7 0
|
10天前
|
JavaScript 前端开发
js遍历对象的方法
js遍历对象的方法
17 1
|
1天前
|
前端开发 JavaScript 算法
在 JavaScript 中,有哪些方式可以达到继承的效果?
在 JavaScript 中,有哪些方式可以达到继承的效果?
7 0
|
3天前
|
JavaScript 前端开发
JavaScript常用的属性
JavaScript常用的属性
|
4天前
|
消息中间件 存储 前端开发
理解JavaScript事件循环机制
理解JavaScript事件循环机制
9 0
|
4天前
|
JavaScript 前端开发
解释一下js的原型和原型链
解释一下js的原型和原型链
7 0
|
7天前
|
前端开发 JavaScript 数据处理
JavaScript中的异步编程及Promise对象
【2月更文挑战第3天】 传统的JavaScript编程模式在处理异步任务时常常会导致回调地狱和代码可读性较差的问题,而Promise对象的引入为解决这一问题提供了一种优雅的解决方案。本文将介绍JavaScript中的异步编程方式以及Promise对象的使用方法和优势,帮助读者更好地理解和运用异步编程技术。
14 8
|
13天前
|
JavaScript 前端开发 索引
【JavaScript】面试手撕数组原型链(易)
续借上文,这篇文章主要讲的是数组原型链相关的考题,有些人可能会纳闷,数组和原型链之间有什么关系呢?我们日常使用的数组forEach,map等都是建立在原型链之上的。举个🌰,如我有一个数组const arr = [1,2,3]我想要调用arr.sum方法对arr数组的值进行求和,该如何做呢?我们知道数组没有sum函数,于是我们需要在数组的原型上定义这个函数,才能方便我们调用,具体代码如下。接下来我们就是采用这种方式去实现一些数组常用的方法。
32 6
|
24天前
|
JavaScript Unix 索引
2022年11月21日13:32:00——T5——JS对象与Date日期函数
2022年11月21日13:32:00——T5——JS对象与Date日期函数
21 0
|
26天前
|
JavaScript 前端开发 Java
JavaScript数组操作示例及对象操作技巧
今天针对javascript的数组的一些常见操作进行一些讲解,希望对给为开发者有帮助。 先看下面常见的三种循环。