-
2021-12-07 11:35:26
java中的继承
class Fa{ } class Zi extends Fa{} interface T{} interface Q{} class T1 implements T,implements Q,extends Zi{ }
java里面的
OOP
很简单。
我的目标是研究js里的OOP和Java的异同,以及优劣
。
js(es5)中的面相对象
function==>构造函数
new function名 ==>创建对象
prototype
==> 父的变量传递给子,子的__proto__
指向这个属性| java:直接把父的所有成员属性和方法给继承过来。(先不管static)。
为什么?javascript中有多态吗?没有。有继承么?没有。继承是干什么的?是让子继承父元素的成员变量和方法的。js中有啥?变量,方法,对象。那js咋整面相对象?hack呗,给个指针个你,让父类对象的,且专门留给子的方法和属性,给子类。子类也拿过来这个指针去搞父类。完了么?没有!既然都是对象了,那构造函数呢?创建对象呢?在子类的__proto__里面有构造器,这样就和类产生关联。
js(es5)里的继承
//class function Fa(){ } //class的静态方法和变量 function Fa(){ name:'', age:18, function method1(){ //do some thing } } //class的成员变量和方法 function Fa(){ } Fa.prototype.name = ''; Fa.prototype.age=18; Fa.prototype.method1=function(){}
为什么js中要有如此奇怪的继承
js的继承是靠上的。
js他对象是属性,他里面prototype更像是一种类型,一种类,一种模板。而且这个类,这个模板,还有构造器。哈哈哈,好像明白了。
1.js中的继承和java比没有类的概念。
2.js更像是对象的继承。
3.js中对象的继承就是java里的创建对象。
他和java克隆的区别有以下几点:
1.克隆他是对象和对象之间的,有同级关系。而继承是有层级关系。
2.克隆他可以通过重写来灵活地达到一个深拷贝的效果。而继承呢,他就是浅拷贝的。改不了。(硬是要改那就不说了)
也有几点联系:
1.我感觉克隆就是一个创建对象嘛,只不过克隆他可以自定义。至于为什么用实现接口的方式,那就是设计者的问题了,和我们无关。定义,js中原型是什么?
原型是属性,是指针,是面相对象中继承的实现
hack
.更多相关内容 -
什么是原型链
2021-03-14 22:18:03对象原型相信大家都这样用过 map :let arr = [0, 1, 2]let doubleArr = arr.map(c => c * 2)console.log(doubleArr) // 0, 2, 4不知道你有没有想过, arr 本身并没有设定 map 属性,那为什么可以用 map 这个函数...对象原型
相信大家都这样用过 map :let arr = [0, 1, 2]
let doubleArr = arr.map(c => c * 2)
console.log(doubleArr) // 0, 2, 4
不知道你有没有想过, arr 本身并没有设定 map 属性,那为什么可以用 map 这个函数呢?
把它打印出来看看:console.log(arr)
// 0: 0
// 1: 1
// 2: 2
// length: 3
// __proto__: Array(0)
出现了一个名为 __proto__ 的对象,如果再将其展开,就会看到所有 Array 对象可以使用的函数;当然我们也可以在其中找到 map 函数,而这也正是例子中所调用的 arr.map 这个函数:console.log(arr.map === arr.__proto__.map) // true
这里出现的 __proto__ 对象,也就是所谓的 原型对象(Prototype) 。
不同于 Java、C# 等基于类(Class) 的面向对象语言,通过定义类、创建实例、指定继承等方式来传递属性及方法;Javascript 则是个基于原型(Prototype)的对语言 ,通过预先建立出的原型对象,当新对象建立时指定对象的原型要参照哪个原型对象。
而当我们调用对象的属性或方法时,若对象本身没有这个属性或方法,JavaScript 会自动寻找它原型中的方法,这也就是为什么可以直接调用 arr.map 而不会出错的原因。
原型链
你可能已经发现在前面的例子中,__proto__ 对象里仍然有 __proto__ 属性:console.log(arr.__proto__) // Array 的 Prototype
console.log(arr.__proto__.__proto__) // Object 的 Prototype
console.log(arr.__proto__.__proto__.__proto__) // null
在上述机制中,每当对象建立时都会绑定原型,既然对象都有原型,对象原型本身也是对象,自然也不例外;由这个例子中我们可以看出:arr 是数组实例,原型是 Array
arr.__proto__ 是数组的原型,原型是 Object
arr.__proto__.__proto__ 是对象的原型,原型是 null
arr.__proto__.__proto__.__proto__ 是 null,没有任何属性
由于每个对象都有原型,这样就形成了一个关联一个、层层相互依赖的从属关系,我们把它们叫做原型链(Prototype Chain) ;通过这种机制,让对象得以使用原型中的属性和方法,并凭借原型链一层一层的按顺序继承,让对象能拥有原型链上所有原型的功能,这就是 JavaScript 对象背后的运作机制。补充:在 JavaScript 中,几乎每个原型链的末端都会是 Object,并最后指向到 null。
使用原型
说了这么多,该来点代码了,接下来就来练习一下原型的建立、设定及修改吧。
先来创建一个新的对象构造函数:function Person(name) {
this.name = name
}Person.prototype.hello = function () {
console.log(`Hello ${this.name}.`)
}let gary = new Person('Gary')
gary.hello() // Hello Gary.Object.getPrototypeOf(gary) // {hello: ƒ, constructor: ƒ}
上面的例子创建了一个简单的对象构造函数 Person(),并在构造函数中设定对象属性。对象的方法中,由于方法不需要让每个对象都独自拥有一份,以避免造成冗余的内存消耗,应该要像前面 Array.prototype.map 的例子那样把对象的方法设定给原型对象(Person.prototype),让这个构造函数创建出来的对象都可以共用这些方法。最后建立一个新的 Person 对象,并通过 getPrototypeOf(obj) 获取新产生对象的原型。Q:为什么不直接用 __proto__ 获取原型对象?
A:因为虽然 __proto__ 被几乎所有的浏览器支持,但它是非标准属性;通过 getPrototypeOf 取得对象的原型是正确的方法。
提醒:Person.prototype 不是 Person 的原型,而是构造函数执行后所建立的新对象的原型;千万不要把构造函数的 prototype 属性与对象的原型搞混!
原型继承
接着再创建新的对象原型,并继承 Person:function Engineer(name, skill) {
Person.call(this, name)
this.skill = skill
}
Engineer.prototype = Object.create(Person.prototype)
Engineer.prototype.constructor = Engineerlet alice = new Engineer('Alice', 'JavaScript')
alice.hello() // Hello Alice.
console.log(alice.skill) // JavaScriptObject.getPrototypeOf(alice)
// Person {constructor: ƒ}
这里建立了新的对象 Engineer 的原型,并通过 Engineer.prototype 的指定,让它的原型继承自 Person.prototype,最后再重新设定 Engineer.prototype.constructor,让构造函数重新指回自己;这样就完成了最基本的原型继承。Q:为什么需要重新设定 constructor?
A:这边功过 Object.create 复制了 Person.prototype 的全部属性,连同 constructor 属性都会被覆盖掉,如果 constructor 属性错误,在做 instanceof 判断时会产生错误的结果;因此这边设定继承时需要再次将 constructor 重新指定回构造函数本身。
修改原型
原型的引用、继承是直接参照到原型对象上,并非是在每个对象都复制一份原型;因此可以利用这个特性,在原型上增加自定义的属性和方法,让所有该类型的对象都能得到新方法;许多针对旧版浏览器的 Polyfill 就是这样实现的。
例如我们在写 Vue 项目的时候,可能都有做过类似的操作,把共用性高的属性方法放到 Vue.prototype 中:Object.defineProperty(Vue.prototype, '$date', { value: dateTimeFormat })
// 之后就可以这样用
vm.$date(dateObj)
这样的确很方便,但也要提醒开大家,当我们在做原型修改的时候要特别小心。接着刚才的例子,如果尝试对 Person 原型中的方法做个修改:Person.prototype.hello = function () {
console.log(`Bye ${this.name}.`)
}gary.hello() // Bye Gary.
alice.hello() // Bye Alice.
如结果所示,当对象原型做修改时,所有原型链上有这个原型的对象,通通都会受到影响,不管对象是在修改前还是修改后创建的。
建议大家除非是 Polyfill,否则应该要极力避免对原生对象的原型进行修改,防止造成可能的意外结果。
ES6 的 Class
看完前面这一大段,是不是觉得心很累?别担心,从 ES6 开始添加了 Class 语法糖,使开发者体验提升了很多。下面把前面的例子用 Class 重构一下:class Person {
constructor (name){
this.name = name
}
// 方法会自动放到 Person.prototype
hello() {
console.log(`Hello ${this.name}.`)
}
}class Engineer extends Person {
constructor (name, skill){
super(name) // 调用 Person 的构造函数
this.skill = skill
}
}let alice = new Engineer('Alice', 'JavaScript')
alice.hello() // Hello Alice.Object.getPrototypeOf(alice)
// Person {constructor: ƒ}
很方便,同样的功能,代码的可读性却提高了不少,繁琐的设定也都能交给语法自动帮你完成。不过方便的语法背后,底层仍然是对象原型及原型链。
总结
以上是 JavaScript 中关于对象原型的说明,希望能帮你理解对象原型,在这个什么都是对象的语言中,充分理解并掌握对象原型,是成为专业码农必须要突破的关卡之一。
-
原型链的使用
2021-03-11 10:50:42这段时间突然有点了解了原型的方法然后看了这个文章感觉很详细...原型链由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链...这段时间突然有点了解了原型的方法然后看了这个文章感觉很详细,就记录一下
原型对象
每个javascript对象都有一个原型对象,这个对象在不同的解释器下的实现不同。比如在firefox下,每个对象都有一个隐藏的__proto__属性,这个属性就是“原型对象”的引用。
原型链
由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回undefined.原型链一般实现为一个链表,这样就可以按照一定的顺序来查找。
示例1
结果
图1
可以看到,当执行ext1.id时,引擎在ext1对象本身中就找到了id属性,因此返回其值0,当执行ext1.getInfo时,ext1对象中没有找到,因此在其原型对象base中查找,找到之后,执行这个函数,得到输出”base”。
我们将上例中的ext1对象稍加修改,为ext1对象加上name属性:
示例2
结果
这个运行效果同样验证了原型链的运行机制:从对象本身出发,沿着__proto__查找,直到找到属性名称相同的值(没有找到,则返回undefined)。
我们对上例再做一点修改,来更好的演示原型链的工作方式:
示例3
结果
应该注意的是,getInfo函数中的this表示原始的对象,而并非原型对象。上例中的id属性来自于ext1对象,而name来自于base对象。如果对象没有显式的声明自己的”__proto__”属性,这个值默认的设置为Object.prototype,而Object.prototype的”__proto__”属性的值为”null”,标志着原型链的终结。
构造器
我们在来讨论一下构造器,除了上边提到的直接操作对象的__proto__属性的指向以外,JavaScript还支持构造器形式的对象创建。构造器会自动的为新创建的对象设置原型对象,此时的原型对象通过构造器的prototype属性来引用。
我们以例子来说明,将Task函数作为构造器,然后创建两个实例task1, task2:
示例4
结果
构造器会自动为task1,task2两个对象设置原型对象Task.prototype,这个对象被Task(在此最为构造器)的prototype属性引用,参看下图中的箭头指向。
图2
由于Task本身仍旧是函数,因此其”__proto__”属性为Function.prototype, 而内建的函数原型对象的”__proto__”属性则为Object.prototype对象。最后Obejct.prototype的”__proto__”值为null。
-
javascript原型和原型链
2021-01-08 18:16:24一、原型规则 1、所有的引用类型(数组、对象、函数)都具有对象特性,即可自由扩展属性(除了“null”) var array=[];array.a=1; var object={};object.a=1; function func(){}; func.a=1; 2、所有的引用类型... -
原型与原型链的理解
2021-03-11 10:50:24前言javascript语言是一种面向对象的语言,它没有"子类"和"父类"的概念,里面所有的数据类型都是对象,这一点与Java非常相似。如何将这些对象联系起来呢?Brendan Eich在考虑设计继承机制的时候,参考了C++和JAVA...前言
javascript语言是一种面向对象的语言,它没有"子类"和"父类"的概念,里面所有的数据类型都是对象,这一点与Java非常相似。如何将这些对象联系起来呢?
Brendan Eich在考虑设计继承机制的时候,参考了C++和JAVA使用new命令,通过调用类的构造函数生成实例的方式,将new命令引入javascript。
C++的写法是:
ClassName *object = new ClassName(param);
Java的写法是:
Person person = new Person();
但是,javascript里面没有“类”这个概念,那么,Brendan Eich决定直接在new后面跟一个构造函数,来生成实例。
原型对象
构造函数是什么?构造函数与其他函数唯一的区别在于调用方式不同。任何函数只要通过new来调用就可以作为构造函数,它是用来创建特定类型的对象。
举例来说,下面定义一个构造函数Animal,表示动物对象的原型。
function Animal(name){this.name =name;
this.sex = 'female';
}
new运算符的缺点
通过new命令来生成一个dog实例:
var dog= new Animal("小K")
这里,构造函数Animal就是实例对象dog的原型!!!Animal里的this关键字就指的是dog这个对象!
new出来的dog对象此时已经和Animal再无联系了!也就是说每一个new出来的实例都有自己的属性和方法的副本,是独立的的!修改其中一个不会影响另一个!
用构造函数生成实例对象,有一个缺点,那就是无法共享属性和方法。
var dog1= new Animal("小A");var dog2= new Animal("小B");
dog2.sex= 'male';
console.log(dog1.sex)//female
console.log(dog2.sex) //male
但是,我们希望构造函数中的sex属性是一个共有属性,那么此时用这样的方法,每个实例中都有一个相同的sex属性,会造成资源极大的浪费!
prototype属性的引入
那么原型对象就即将登场了!Brendan Eich决定给每一个构造函数都设置一个prototype属性,这个属性就指向原型对象。其实原型对象就只是个普通对象,里面存放着所有实例对象需要共享的属性和方法!所以,我们把需要共享的放到原型对象里,把那些不需要共享的属性和方法存在在构造函数里!
function Animal(name){this.name =name;
}
Animal.prototype.eat= 'food';var dog1= new Animal("小A");var dog2= new Animal("小B");
console.log(dog1.eat)//food
console.log(dog1.eat) //food
Animal.prototype.eat= 'water';
console.log(dog1.eat)//water
console.log(dog2.eat) //water
可以看出,修改prototype属性会影响它的所有实例的eat的值!!
实例一旦创建出来就会自动引用prototype对象的属性和方法!所以实例对象的属性和方法一般分为两种:一种是自身的,一种是引用自prototype的。
具体实现是这样的:
每当代码读取某个对象的某个属性的时候,都会执行一次搜索。首先从对象实例本身开始,如果在实例中找到了该属性,则返回该属性的值,如果没有找到,则顺着原型链指针向上,到原型对象中去找,如果如果找到就返回该属性值。
这里要提一点,如果为对象实例添加了一个属性与原型中同名,则该属性会屏蔽掉原型中的同名属性,不会去修改它!使用delete可以删除实例中的属性提到delete那要插一句~delete只能删除对象下的属性,不能删除变量和参数!
原型链
事实上,js里依靠"原型链"(prototype chain)模式来实现继承。
上面说完原型对象。下面要扒一扒proto、prototype、constructor。
proto:事实上就是原型链指针!!
prototype:上面说到这个是指向原型对象的
constructor:每一个原型对象都包含一个指向构造函数的指针,就是constructor
继承实现方式:
为了实现继承,proto会指向上一层的原型对象,而上一层的结构依然类似,那么就利用proto一直指向Object的原型对象上!Object.prototype.__proto__ = null;表示到达最顶端。如此形成了原型链继承。
下面有个图解非常经典,可以自己手画了一遍去理解,真的非常有效~
大致总结一下就是:
1、Object是作为众多new出来的实例的基类 function Object(){ [ native code ] }
2、Function是作为众多function出来的函数的基类 function Function(){ [ native code ] }
3、构造函数的proto(包括Function.prototype和Object.prototype)都指向Function.prototype
4、原型对象的proto都指向Object.prototype
5、Object.prototype.proto指向null
参考资料:
-
javascript中的原型链深入理解
2020-12-10 11:05:55要弄清楚原型链就要先弄清楚 function 类型,在javascript中没有类的概念,都是函数,所以它是一门函数式的编程语言。类有一个很重要的特性,就是它可以根据它的构造函数来创建以它为模板的对象。在javascript中,... -
javascript 原型与原型链的理解及应用实例分析
2020-11-21 04:49:55本文实例讲述了javascript 原型与原型链的理解及应用。分享给大家供大家参考,具体如下: javascript中一切皆对象,但是由于没有Class类的概念,所以就无法很好的表达对象与对象之间的关系了。 比如对象A与对象B之间... -
跟我学习javascript的prototype原型和原型链
2021-01-21 11:32:13每个函数都有一个prototype属性,这个属性是指向一个对象的引用,这个对象称为原型对象,原型对象包含函数实例共享的方法和属性,也就是说将函数用作构造函数调用(使用new操作符调用)的时候,新创建的对象会从原型... -
深入浅出理解javaScript原型链
2020-12-01 10:36:19本文实例讲述了javaScript的原型链。分享给大家供大家参考。具体分析如下: 对于javascript原型链,以前都觉得是个很深的东西,一直没有理解很明白,今天看了一些介绍后,发现这张图,表示再没有什么语言能比这张... -
分析javascript原型及原型链
2020-11-28 03:55:22我们创建的每个函数都有一个 prototype (原型)属性,这个属性是一个指针,指向一个原型对象,而这个原型对象中拥有的属性和方法可以被所以实例共享。 function Person(){ } Person.prototype.name = "Nicholas"; ... -
javascript 原型与原型链的理解及实例分析
2020-12-13 06:13:48本文实例讲述了javascript 原型与原型链的理解。分享给大家供大家参考,具体如下: javascript中一切皆对象,但是由于没有Class类的概念,所以就无法很好的表达对象与对象之间的关系了。 比如对象A与对象B之间,它们... -
浅谈javascript原型链与继承
2020-12-11 11:01:23js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解。 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询obj的原型,我们通过判断obj的原型... -
理解javascript中的原型和原型链
2020-12-12 09:27:48原型 大家都知道,JavaScript 不包含传统的类继承模型,而是使用 prototype 原型模型。代码实现大概是这样子的 function Student(name){ this.name = name; } var Kimy = new Student("Kimy"); Student.... -
javascript原型链继承用法实例分析
2021-01-19 18:11:08本文实例分析了javascript原型链继承的用法。分享给大家供大家参考。具体分析如下: 代码如下:function Shape(){ this.name = ‘shape’; this.toString = function(){ return this.name; } } ... -
学习javascript面向对象 理解javascript原型和原型链
2020-11-24 03:57:28【原型链】每个构造函数都有一个对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么,如果原型对象等于另一个原型的实例,此时的原型对象将包含一个指向另一个原型的指针,... -
深入理解javascript原型链和继承
2021-01-21 12:33:22在上一篇文章中,介绍了原型的概念,了解到在javascript中构造函数、原型对象、实例三个好基友之间的关系:每一个构造函数都有一个“守护神”——原型对象,原型对象心里面也存着一个构造函数的“位置”,两情相悦,... -
javascript prototype 原型链
2021-01-19 19:03:06既然prototype是对象的“原型”,那么由该函数构造出来的对象应该都会具有这个“原型”的特性。事实上,在构造函数的prototype上定义的所有属性和方法,都是可以通过其构造的对象直接访问和调用的。也可以这么说,... -
javascript 原型链维护和继承详解
2020-12-08 23:19:47两个原型 很多人都知道javascript是原型继承,每个构造函数都有一个prototype成员,通过它就可以把javascript的继承演义的美轮美奂了. 其实啊,光靠这一个属性是无法完成javascript的继承. 我们在代码中使用的... -
javascript原型链学习记录之继承实现方式分析
2020-11-27 05:53:58本文实例讲述了javascript原型链学习记录之继承实现方式。分享给大家供大家参考,具体如下: 在慕课网学习继承的笔记: 继承的几种方式: ① 使用构造函数实现继承 function Parent(){ this.name = 'parent'; } ... -
javascript学习笔记(五)原型和原型链详解
2020-12-11 18:36:32私有变量和函数 在函数内部定义的变量和函数,如果不对外提供接口,外部是无法访问到的,也就是该函数的私有的变量和函数。 代码如下: [removed] function Test(){ var color = “blue”;//私有变量 ... -
关于JavaScript 原型链的一点个人理解
2021-01-21 11:17:18而且每个对象都有一个internal slot[[prototype]],这才是原型链连接起来的关键。诚然,我们可以为一个对象设置prototype property,但这又怎么样呢,这只是表象;后面暗藏杀机。 好,那我可以用isPrototypeOf()来... -
深入理解JS继承和原型链的问题
2021-01-19 16:05:51对于那些熟悉基于类的面向对象语言(Java 或者 C++)的开发者来说,JavaScript 的语法是比较怪异的,这是由于 JavaScript 是一门动态语言,而且它没有类的概念( ES6 ...这种一级一级的链结构就称为原型链(prototype -
javascript基于原型链的继承及call和apply函数用法分析
2021-01-19 16:18:011. 继承是面向对象编程语言的一个重要特性,比如Java中,通过extend可以实现多继承,但是JavaScript中的继承方式跟JAVA中有很大的区别,JS中通过原型链的方式实现继承。 (1)对象的原型:因为JS中,函数也是对象,... -
[js高手之路]图解javascript的原型(prototype)对象,原型链实例
2020-12-12 04:46:31我们通过原型方式,解决了多个实例的方法共享问题,接下来,我们就来搞清楚原型(prototype),原型链的来龙去脉。 function CreateObj(uName) { this.userName = uName; } CreateObj.prototype.showUserName = ... -
一张图搞懂原型、原型对象、原型链
2021-02-28 13:30:38每个函数都有一个特殊的属性叫作原型(prototype)每个对象拥有一个原型对象 [[Prototype]] / __proto__ / Object.getPrototypeOf(object1)通过原型对象一级一级的往上找的这个过程就是原型链原型每个函数都有一个... -
javascript教程之不完整的继承(js原型链)
2021-01-19 19:16:50Javascript的继承和标准的oop继承有很大的区别,Javascript的继承是采用原型链的技术,每个类都会将“成员变量”和“成员函数”放到 prototype 上,Js++都过superclass将其链接起来,即 C.prototype.superclass = C.... -
原型和原型链详解
2020-06-04 18:29:03原型和原型链怎么来的? 1994年,网景公司(Netscape)发布了Navigator浏览器0.9版,但是刚开始的Js没有继承机制,更别提像同时期兴盛的C++和Java这样拥有面向对象的概念。在实际的开发过程中,构造函数内部的属性... -
javascript中对象的定义、使用以及对象和原型链操作小结
2021-01-21 11:38:08本文实例总结了javascript中对象的定义、使用以及对象和原型链操作。分享给大家供大家参考,具体如下: 1. 除了5种基本类型外,JS中剩下的就是对象 (1)对象的定义: 直接定义: var test={x:1,y:1} new方式创建... -
js的继承与原型链
2021-03-13 18:57:20对于使用基于类的语言,如 Java 的开发人员,js 令人困惑,因为它是动态的,并且本身不提供一个 class 实现。(在 ES2015/ES6 中引入了 class 关键字,但那只是语法糖,JavaScript 仍是基于原型)。 谈到继承时,js ... -
原型及原型链详解
2020-02-28 22:37:55每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另...这就是所谓的原型链的基本概念。——摘自《javascript高级程序设计》