当前位置: 首页 > Web前端 > HTML5

动态图形JavaScript:原型继承

时间:2023-04-05 01:14:52 HTML5

前言你有没有想过为什么我们可以在JS中使用一些内置的属性和方法,比如.length,.split(),.join()?我们没有明确声明它们,那么它们是从哪里来的呢?只是不要说“这在JS中很神奇!”。其实,这些都是因为一种叫做原型继承的东西。它很棒,你经常使用它,但你可能没有注意到它!构造函数我们经常需要创建许多相同类型的对象。想象一下,我们有一个全是狗的网站~对于每只狗,我们都需要一个对象来代表它!为了不每次都创建一个新的对象,需要写一个构造函数(后面会讲到ES6中的类~)。有了构造函数,就可以使用new关键字来创建狗的实例(instance)。每只狗都有名字、品种、颜色和吠叫方法。当我们创建Dog构造函数时,它并不是我们创建的唯一对象(记住函数也是对象)。自动创建另一个原型对象。默认情况下,这个对象有一个构造函数属性指向我们的Dog构造函数。Dog构造函数上的原型属性是不可枚举的,这意味着当您尝试访问对象属性时,该属性不会出现。但它仍然存在!原型继承就好了~那为什么要有这个属性对象呢?首先,让我们创造几只狗。为简单起见,我们称它们为dog1和dog2。dog1是Daisy,一只可爱的拉布拉多犬!dog2的名字叫Jack,是一只勇敢的杰克罗素犬(JackRussell)~让我们把dog1打印到控制台,然后展开它的属性:可以看到我们添加的属性有:name、breed、color和bark,但是看,还有一个__proto__属性!它也是不可枚举的,所以通常我们在获取对象属性时看不到它。我们展开看看:是不是和Dog.prototype长得一样?你猜怎么着,这个__proto__是对Dog.prototype的引用。这就是原型继承的全部内容:构造函数创建的每个实例都可以访问构造函数的原型。原型继承的好处那么为什么这很酷呢?有时我们有每个实例共享的属性。比如bark方法:在每个实例中都是一样的,那为什么每次创建一个新的实例都要创建一个新的bark方法,这显然是浪费内存。相反,我们可以将bark方法添加到Dog.prototype!这样,每当我们访问一个实例的属性时,引擎首先检查该属性是否定义在该实例上。如果没有找到,它会通过__proto__属性沿着原型链继续查找。不止一层这只是一个步骤,但实际上可以包含多个步骤!如果继续,您可能会注意到,当我展开Dog.prototype的__proto__对象时,我没有包含属性。由于Dog.prototype本身是一个对象,这意味着它实际上是Object构造函数的一个实例。这意味着Dog.prototype也有一个指向Object.prototype的__proto__属性。例如,.toString()方法。它是在dog1上定义的吗?很明显不是。那么Dog.prototype上有吗?也不!其实就是在Dog.prototype.__proto__上定义的,也就是Object.prototype。ES6中的类之前我们使用构造器的方法(functionDog(){...})。事实上,ES6为构造函数和原型提供了更简单的语法:类(Classes)只是构造函数。语法糖。一切都以同样的方式工作!我们使用class关键字来定义一个类。每个类都有构造函数,基本对应ES6中构造函数的写法。我们要添加到原型原型的属性和方法可以直接在类中定义。类的另一个好处是我们可以轻松地扩展其他类。类继承假设我们要添加另一种狗,吉娃娃。为了便于理解,我们只添加了一个name属性。但是吉娃娃也可以有自己的特殊叫声!和普通的调用不同,吉娃娃的调用可能比较小~在子类中,我们可以通过super关键字来访问父类的构造函数。当然,参数也是参照父类的构造函数传入的。myPet可以访问Chihuahua.prototype和Dog.prototype(当然还有Object.prototype,因为Dog.prototype是一个对象)。由于Chihuahua.prototype上有一个smallBark方法,Dog.prototype上有一个bark方法,我们可以访问myPet实例上的smallBark和bark方法。原型的终结正如您想象的那样,原型链不会永远持续下去。最终会有一个原型等于null的对象:它就是Object.prototype。如果我们尝试访问一个在本地或原型链上不存在的属性,我们最终将返回undefined。Object.create尽管上面已经解释了构造函数和类,但还有另一种方法可以使用Object.create方法来原型化对象。通过这个方法,我们创建了一个新的对象,并指定了这个对象的原型是什么。只需将现有对象传递给Object.create方法即可。创建的对象是基于我们作为原型传入的对象。看例子:我们打印一下me,可以看到me这个对象我们并没有添加其他属性,但是访问它有一个__proto__属性,这个属性指向对象person有name和age。person对象的__proto__属性指向Object.prototype。全文到此结束,希望对大家学习原型继承有所帮助作者:事件循环(EventLoop)动态图形JS:JavaScriptEngine动态图形之JS:原型继承【本文】参考链接JavaScript可视化:原型继承