JS对象继承与原型链

1.以复制方式实现的继承

1.1浅拷贝

基本类型的复制

 1 var parent = {
 2     lanage: "chinese"
 3 }
 4
 5 var child = {
 6     name: "xxx",
 7     age: 12
 8 }
 9
10 function extend(parent, child) {
11     var child = child || {};
12     for (const propertype in parent) {
13         child[propertype] = parent[propertype];
14     }
15 }
16
17 extend(parent, child);
18
19 console.log(child);//{ name: ‘xxx‘, age: 12, lanage: ‘chinese‘ }

以上代码中,通过一个extend()函数,将父对象parent的属性遍历赋给子对象child,从而实现继承。

但是这种字面量复制的方式存在巨大的缺陷,当父对象有引用类型的属性时,通过这么复制的方式,就像上一节中的var b = a一样,只会将a对象的引用赋给b对象,结果两者是指向同一个对象内存的,继承出来的子对象的属性是同一个,显然是不能满足需求的,(基本类型之间画等号是值的复制,引用类型之间画等号是引用的复制)所以就需要另谋出路。

1.2.深拷贝

利用递归加类型判断复制引用类型

 1 var parent = {
 2     lanage: "chinese",
 3     address: {
 4         home: "gansu",
 5         office: "xian"
 6     },
 7     schools: ["xiaoxue", "zhongxue", "daxue"]
 8 }
 9
10 var child = {
11     name: "xxx",
12     age: 12
13 }
14
15 function extendDeeply(parent, child) {
16     var child = child || {};
17     for (const propertype in parent) {
18         //首先判断父对象的当前属性是不是引用类型
19         if (typeof parent[propertype] === "object") {
20             //再判断该引用类型是不是数组,是则给子对象初始化为空数组,否则初始化为空对象
21             child[propertype] = Array.isArray(parent[propertype]) ? [] : {};
22             //递归调用自己,将父对象的属性复制到子对象
23             extendDeeply(parent[propertype], child[propertype]);
24         } else {
25             //基本类型直接复制
26             child[propertype] = parent[propertype];
27         }
28     }
29 }
30
31 extendDeeply(parent, child);
32 console.log(child);
33 child.schools[0] = "qinghua"; //改变子对象的属性值
34 child.address.home = "tianjin";
35
36 console.log(child.schools[0]); //qinghua
37 console.log(parent.schools[0]); //xiaoxue
38 console.log(child.address.home); //tianjin
39 console.log(parent.address.home); //gansu

可见此时子对象的改变并不会影响到父对象,父子彻底决裂。这便是深拷贝实现的继承。

注意:for in 是可以遍历数组的,结果为数组元素下标。

2.以构造函数实现继承

 1 function Parent() {
 2     this.name = "name";
 3     this.age = 12;
 4 }
 5
 6 function Child() {
 7     Parent.call(this);
 8     this.language = "chinese";
 9 }
10
11 var child = new Child();
12 console.log(child);//{ name: ‘name‘, age: 12, language: ‘chinese‘ }
13 child.name = "swk";
14 console.log(new Parent().name);//name

如上所示,通过在子类构造函数中调用父类构造函数,将父类属性继承到子类对象上,new出来的每一个子类对象都是独立的实例,这种方式更符合面向对象的思想。

3.以原型方式实现继承

 1 var person = {name: "pname"};
 2
 3 function myCreate(person) {
 4     var ins;
 5     function F() { };
 6     F.prototype = person;
 7     ins = new F();
 8     return ins;
 9 }
10
11 var c = new myCreate(person);
12 console.log(c.name); //pname
13 console.log(c); //{}

如上所示,将一个构造函数的原型替换为父对象,然后返回该构造函数的实例,如此一来创建的子对象就是F的实例,并且其原型为父对象,所以c.name可以被查找到,但子对象c本身是没有属性的。这种直接重写prototype原型对象的弊端在于会断掉原本的原型链,即没有了继承自Object的方法,和给原型对象prototype上添加属性是不同的。

4.JS原型链

盗一波大神的经典图

从该图可以看出两点

4.1从原型prototype层面:

  • 不论是 new Foo()自定义构造函数,new Object()系统构造函数,还是对象字面量创建出来的对象,只要是对象,其原型最终都指向Object.prototype对象,自定义的多绕了一步,就像Java里说的,Object.prototype是一切JS对象的根对象。
  • 函数的原型都指向Function.prototype,而在JS中,函数也是对象的一种,所以符合第一条。

4.2从构造器constructor层面

  • 首先对象的构造器肯定是指向他的构造函数,f1, f2指向Foo(), o1, o2指向Object()。
  • 而构造函数Foo()和Object()的constructor属性最终指向函数构造器Function()。

原文地址:https://www.cnblogs.com/jixiaohua/p/10514239.html

时间: 2024-11-25 05:51:41

JS对象继承与原型链的相关文章

一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)

上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 = "张三"; } function Obj2() { } Obj2.prototype = new Obj1(); var t2 = new Obj2(); alert(t2.name1); 这里有个明显的缺点就是:(如果父类的属性是引用类型,那么我们在对象实例修改属性的时候会把原型中

js(4) 继承与原型链

一:使用原型链来实现继承 在介绍原型链之前,要引入构造函数,原型,和实例的关系 构造函数都有一个原型对象,在原型对象中存在一个指向构造函数的指针(constructor),在实例中包含一个指向原型对象的内部指针(prototype) 构建原型链的原理是让一个类型的原型对象等于另一个类型的实例 当使用new 操作符构造实例的时候,实例会拥有构造函数原型中的属性和方法 实现代码如下: function SuperType(){ this.property=true; }//在SuperType的原型

js继承与原型链

对于那些熟悉基于类的面向对象语言(Java 或者 C++)的开发者来说,JavaScript 的语法是比较怪异的,这是由于 JavaScript 是一门动态语言,而且它没有类的概念(虽然 class 是个保留字,不能作为变量名来使用). 继承方面,JavaScript 中的每个对象都有一个内部私有的链接指向另一个对象,这个对象就是原对象的原型.这个原型对象也有自己的原型,直到对象的原型为 null 为止(也就是没有原型).这种一级一级的链结构就称为原型链. 虽然这通常会被称作 JavaScrip

js继承之原型链方式实现

温故而知新: 在之前的文章已经重点了解了原型对象,今天就理一理这个原型对象在原型链式的继承中的使用 function a(x,y){this.x=x;this.y=y;} //定义一个函数,当构造函数用(正经从程序用大写哈!) 原型对象上添加属性 a.prototype.ayuanxing="a原型属性"; new 一个对象看看咯: 同样的,定义一个b函数: function b(z){this.z=z}; b.prototype.byuanxing="b原型属性"

JS对象继承篇

JS对象继承篇 ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的 原型链 其基本思路是利用原型让一个引用类型继承另一个引用类型的属性和方法 function Person(){ this.name = "Person"; } Person.prototype.getName = function(){ return this.name; }; function SuperPerson(name,sex){ this.name = name; this.sex

JS对象中的原型

对象的原型:每个对象都连接一个原型对象,并且它可以从中继承属性.所有通过对象字面量创建的对象都连接到object.prototype.当你创建一个新对象时,你可以选择某个对象作为它的原型.原型连接在更新时不起作用.当我们对某个对象作出改变时,不会触及该对象的原型.原型连接只有在检索值的时候才被用到.如果我们尝试去获取对象的某个属性值,但该对象没有此属性名,那么JS会试着从原型对象中获取属性值,如果那个原型对象也没有该属性,那么再从它的原型中找,以此类推,直到该过程最后到达终点Object.pro

继承与原型链

对于那些熟悉基于类的面向对象语言(Java 或者 C++)的开发者来说,JavaScript 的语法是比较怪异的,这是由于 JavaScript 是一门动态语言,而且它没有类的概念(虽然 class 是个保留字,不能作为变量名来使用). 继承方面,JavaScript 中的每个对象都有一个内部私有的链接指向另一个对象,这个对象就是原对象的原型.这个原型对象也有自己的原型,直到对象的原型为 null 为止(也就是没有原型).这种一级一级的链结构就称为原型链. 虽然这通常会被称作 JavaScrip

继承和原型链

继承方面,JavaScript 中的每个对象都有一个内部私有的链接指向另一个对象,这个对象就是原对象的原型.这个原型对象也有自己的原型,直到对象的原型为 null 为止(也就是没有原型).这种一级一级的链结构就称为原型链. 虽然这通常会被称作 JavaScript 的弱点之一,实际上这种原型继承的模型要比经典的继承模型还要强大.虽然在原型模型上构建一个经典模型是相当琐碎的,但如果采取其他方式实现则会更加困难. 基于原型链的继承 继承属性 JavaScript 对象有两种不同的属性,一种是对象自身

关于JavaScript的原型继承与原型链

在讨论原型继承之前,先回顾一下关于创建自定义类型的方式,这里推荐将构造函数和原型模式组合使用,通过构造函数来定义实例自己的属性,再通过原型来定义公共的方法和属性. 这样一来,每个实例都有自己的实例属性副本,又能共享同一个方法,这样的好处就是可以极大的节省内存空间.同时还可以向构造函数传递参数,十分的方便. 这里还要再讲一下两种特色的构造函数模式: 1.寄生构造函数从形式上来看,这种模式和工厂模式并无区别: function Person(name, age, job){var o = new O