对象与原型对象上篇

    13-2对象与原型对象

      13-2-1对象的分类

      在ES6之前,对象可以分为2大类,分别是原生对象和宿主对象。

      ●原生对象

      原生对象又可以分为2类:内置对象和自定义对象。例如前面我们学习过的Date、Math、 正则、数组等,这些就是典型的内置对象。它们是JavaScript这门语 言本身所内置的,我们直接使用即可。

      而自定义对象则是我们开发人员自己定义的对象,例如在JS基础中介绍过的使用{}快速生成对象。这样的对象就可以被称之为自定义对象。

      。宿主对象

      顾名思义,就是依存于某一个特定的环境才会有的对象。一旦离开了特定的环境,则这些对象将不存在。例如前面我们在讲解DOM编程时介绍过

      的widnow、navigator 、history 等对象,这些都是依赖于浏览器环境的。一旦脱离了浏览器环境,这些对象也就不存在了。

      在ES6中,对象的类别得到了扩充,分为了4个类别,分别是普通对象,外来对象,标准对象和内置对象。

      13-2-2原型对象



迷途 2019/7/23 星期二 19:14:34

迷途 2019/07/23 19:14:33

      let Computer = function(name,price)f

      this. name = name;this.price = price;

      112CiE Tobject#t U35Rreturn (

      name : xiejie"t

      showSth : functíon()

      console, log("another object");

      console. log(this); 11 FJEDthis1

      Computer, protatype. showSth = function()f

      console. log(this); 11 JEDWthis1311

      let apple = new Computer("S R" , 12000);console. log(apple.name); 11 xiejieapple. showSth();11 another object

      11 [ name: 'xiejie', showSth: [Function: showSthJ ]

imit E 7ĩ83513. EXíEJLZE. kẞs pQiã gg üïxT e tiRO1EfẞxtE. this QUsft5 bs f5IJ4B


19:15:01
迷途 2019/7/23 星期二 19:15:01

迷途 2019/07/23 19:15:01

      用new运算符调用函数时,该函数总会返回- -个对象,通常情况下,构造函数里面的this就指向返回的这个对象。示例如下:

      Let Computer = function(name, price){

      this.name = name;this,price F price;}

      Computer . prototype. showSth = function(){

      console. log(this); //打印出this所指向的对象console. log('这是一台${this . name}电脑);}

      let apple = new Computer("苹果",12000);console. log( apple. name);//苹果console. log(apple. price);//12000

      apple, showSth();//Computer { name; ' 苹果’,price: 12000 }这是: -台苹果电脑Let asus = new Computer("华硕" , 5000);console. log(asus. name);//华硕console. log (asus. price);//5000

      asus. showSth();//Computer { name; ' 华硕’,price: 5000 }这是一 台华硕电脑

      这里,我们分别实例化出来了两个对象apple和asus。那么,这两个对象就有各自的属性值。



迷途 2019/7/23 星期二 19:15:11

13-3-2 ES6类的声明
ES6中,已经开始越来越贴近其他的高级语言了。在ES6中有了类这个概念,使用class来创建类,然后从类里面实例化对象。
但是,需要说明的是,虽然有了class这种关键字,但是这只是一种语法糖,背后对象的创建,还

是使用的是原型的方式。
具体示例如下:




迷途 2019/7/23 星期二 19:15:23

迷途 2019/07/23 19:15:22

13-3类与对象的创建

在前面的第一-小节,我们讲述了什么是面向对象,以及什么是类,还有类和对象之间的关系。紧接着在第二小节我们话锋-转,阐述了JavaScript里面不存在类的概念,而是基于一门基于原型的语言。

既然JavaScript里面不存在类,那么为什么我们还要在第- -小节花大量的篇幅来介绍面向对象里面的类呢?实际上,在JavaScript中 虽然没有类,但是可以通过构造函数来模拟其他编程语言里面的类。从而从构造函数里面实例化对象出来。所以在这- -小节, 我们就来看-下JavaScript中如何书写构造函数来模拟其他语言中的类的。

13-3-1构造函数

JavaScript是- -个]很特殊的语言,在ES6之 前都没有类的概念(注: ES6新增了class关键字),而是通过构造函数来模拟其他编程语言里面的类的。构造函数实际上也是函数,不过这种函数是专门用于生产对象的,所以被称之为构造函数。它的外表和普通函数- -模-样,区别只是在于被调用的方式.上面。

构造函数的函数名有一个不成文的规定,就是首字母要大写,以便和普通函数进行区分。下面的例子就演示了在JavaScript中如何书写一个构造函数:



迷途 2019/7/23 星期二 19:15:33

迷途 2019/07/23 19:15:33

13-3-1构造函数

JavaScript是一门很特殊的语言,在ES6之前都没有类的概念(注: ES6新增了class关键字),而是通过构造函数来模拟其他编程语言里面的类的。构造函数实际上也是函数,不过这种函数是专]用于生产对象的,所以被称之为构造函数。它的外表和普通函数一模-样,区别只是在于被调用的方式上面。

构造函数的函数名有一个不成文的规定,就是首字母要大写,以便和普通函数进行区分。下面的例子就演示了在JavaScript中如何书写一个构造函数:

      Let Computer = function(name, price){

      this.name = name;this.price = price;

      Computer. prototype. showSth = function(){

      console. log(这是-台${this. name}电脑);}

这里,我们创建了一-个Computer类,这个类有两个成员属性,分别是name和price,有一-个成员方法,是showSth()。但是可以看到,这里的成员方法showSth()是书写在Computer类的prototype,上面的。



迷途 2019/7/23 星期二 19:15:46

具体示例如下:
class Computer{
//构造器
constructor(name, price){
this. name = name;this.price = price;

}
//原型方法showSth(){
console.log('这是一台${this .name}电脑^ );

}
}
Let apple = new Computer("苹果" , 12000); console. log(apple.name);//苹果console. log( apple. price);//12000apple. showSth();//这是一台苹果电脑




迷途 2019/7/23 星期二 19:15:57

迷途 2019/07/23 19:15:57
PToto_
{})
prototype
constructor
[Function Object]
. proto_
Dror
[Function J
o
constructor
原型对象) Dron
C

_Proto__
Otyoefor

.proto_
"Clor
构造函数
o
( [Function Function]
)
constructor
、对象
COS
Arravll. Nuncel].Booleant. Singll.Functionll. ablectl自定义购值品报导

(对象与原型对象关系图)
通过上面的图我们可以得出以下的结论:
●每一个对象都有一个原型对象。我们可以通过_ proto__ 来访问到某个对象的原型对象●通过_ _proto__ 一直向上寻找原型对象的话,最终会找到null
●一个构造函数的prototype属性指向-一个对象,而这个对象是通过该构造函数实例化出来
的对象的原型对象
●JavaScript中的根对象是0bject.prototype对象。object . prototype对象是一一个空对
象。我们在JavaScript中遇到的每个对象,实际上都是从0bject . prototype对象克隆而来的。0bject. prototype对象就是它们的原型。而object. prototype对象的原型为null。




迷途 2019/7/23 星期二 19:16:08

13-2-2原型对象
JavaScript里面,没有类这个概念,只有原型的概念。在JavaScript里 面的每一个对象, 都有一个原型对象,而原型对象上面也有一个自己的原型对象,一层一-层向上找,最终到达null。这听起来感觉有点复杂,这里我们将通过- -张图来进行解释,如下图:




迷途 2019/7/23 星期二 19:16:20

迷途 2019/07/23 19:16:19
这里,我们分别实例化出来了两个对象apple和asus。那么,这两个对象就有各自的属性值。
但用new调用构造函数时,还要注意一个问题, 如果构造函数显式地返回了一个object类型象,那么此次运算结果最终会返回这个对象,而不是我们之前所期待的this,这里我们通过的两段代码来搞清楚构造函数是否显式返回object类型对象之间的区别,如下:

正常情况,构造函数没有返回object类型对象,this指向实例化出来对 象
Let Computer = function (name ,price){
this. name = name;this.price = price;

Computer . prototype. showSth = function(){
console. log(this); //打印出this所指向的对象

}
Let apple = new Computer("苹果",12000);console. log(apple.name); //苹果
apple. showSth(); // Computer { name: ' 苹果’,price: 12000 }

构造函数显式的返回一个object类型的对象,那么最终使用的就是手动返回的这个对象。
Let Computer = function (name, price){
this. name = name;this.price = price;




迷途 2019/7/23 星期二 19:16:29


      3. constructorl

      i@i5 constructor Æ', F*í]ẞJIê#EJ- ↑Xj ŸẞÆft4. tGiEiš, ñtãiZ↑XfXRXf#жR, 5Jk0F:

      let Computer = function(name,price)[

      this. name = name;this.price = price;]

      Computer, prototype. showSth = function()f

      console. log(' i&Æ- a$íthis . name]@i );]

      let apple = new Computer("#Q" , 12000);

      console. log(apple.const ructor);// [Function: Computer]

      I



迷途 2019/7/23 星期二 19:16:39

迷途 2019/07/23 19:16:38

      关键字来提供不同的访问权限。但是在JavaScript中并没有提供对这些关键字的支持。

      不过在JavaScript中要实现封装的方法也非常简单,可以利用函数的作用域来进行模拟。在声明属性的时候,添加关键字(et、const、 var)即可。原因也非常简单,因为构造函数也是函数,既然是函数就会有函数作用域,所以在属性的前面添加了关键字之后使其成为一个局部变量,外部自然而然也就访问不到了。示例如下:

      Let Computer = function name, price){

      this.name = name ;Let price = price;

      Computer. prototype. showSth = function(){

      console. log(这是一台${this. name}电脑~ );}

      Let apple = new Computer("苹果”,12000);

      console. log(apple. name);//苹果

      console. log(apple. price);//undefinedconsole. log(apple._ price);//undefined

      -般来讲,对于私有属性,有一个不成文的规定,那就是习惯使用_开头来命名私有属性。这里我们可以看到,由于我们对price属性进行了封装,所以外部无法访问到。



迷途 2019/7/23 星期二 19:16:50

迷途 2019/07/23 19:16:49
13-3-3静态方法
所谓静态方法,又被称之为类方法。顾名思义,就是通过类来调用的方法。静态方法的好处在于不需要实例化对象,直接通过类就能够进行方法的调用。

ES6创建类的方法的时候,可以给方法前面添加一个关键字static,来创建一个静态方法。
class Computer{
//构造器
const ructor(name, price){
this.name = name;this.price = price;

}
//原型方法
showSth(){ T
console. log( .这是一台${this . name}电脑);

//静态方法
static comStruct(){
console. log("电脑由显示器,主机,键鼠组成");

}
Computer. comStruct(); 
//电脑由显示器,主机,键鼠组成




迷途 2019/7/23 星期二 19:16:58


4. instanceofjklF7

      l

#JF- -↑XJXE2€- -↑133315J. s↓# iẞtrue, EJtiEfalse

      let Computer = function(name, price)f

      this.name = name;this.price = price;

      Computer. prototype. showSth = function()(

      console. log(' i&- a$[this, name]@Æ" );]

      let apple = new Computer("E R", 12000); .

      console. log(apple instanceof Computer);//trueconsole. log(apple instanceof Array);//false


19:17:09
迷途 2019/7/23 星期二 19:17:09

迷途 2019/07/23 19:17:08

6. hasOwnProperty(

#Jí-↑4ÆÆXÆX$*# LñiZMM#xæ L õẞmTЖÉJ. $ẞ#4#a, J!i@true, SOR€ÉmmxTжÉ], J!JjEfalse

      let Computer = function (name, price)[

      this.name = name;this.price = price;

      Computer. prototype . showSth = function()f

      console. log(' iXk B$[this. name]Rü );]

      Computer. prototype.test = "this is a test";let apple = new Computer("E R" , 12000);console. log(apple.test);//this is a test

      console. log( apple. has0wnP roperty("test"));//falseconsole. log( apple: has0wnProperty("name"));//true



迷途 2019/7/23 星期二 19:17:31

迷途 2019/07/23 19:17:30

x- 1. prototype和_ proto_ ^-2. Object.getPrototypeC. 3. constructor属性. 4. instanceof操作符- 5. isPrototypeOf0. 6. hasOwnProperty03 13-5封装
. 13-5-1 封装基本介绍13-5-2存取器白13-6继承
13-6-1继承基本介绍
继承的好处. 继承的缺点白13-6-2对象冒充
L方法借用模式.13-6-3原型继承. 13-6-4 ES6继承方式白13-7多态(选修)
-13-7-1 多态简介. 13-7-2实现多态13-7-3多态的意义田13-8 this的指向
-13-9内置对象添加方法13-10属性特性以及描述符13-11基于对象创建对象a 13-12混入技术
-13-12-1浅复制与深复制13-12-2用mixin函数添加总结

13-6-1继承基本介绍
在程序语言中,面向对象里面的继承是指一个子类去继承-个父类。子类继承了父类之后,父类所有的属性和方法都自动都拥有了。

继承的好处
继承最大的好处,就在于代码复用。例如有两个类,这两个类的属性和方法基本相同,那么我们就可以考虑给这两个类写-一个父类

继承的缺点
首先如果继承设计得非常复杂,那么整个程序的设计也会变得庞大和臃肿。甚至经常会出现"大猩猩与香蕉"的问题。"大猩猩与香蕉"这个名字来自于Erlang编程语言的创始人Joe Armstrong的文章:你想要一个香蕉,但是得到的是拿着香蕉和整个丛林的大猩猩。

还有一个问题就是,如果是像C+ +那样的多继承语言,那么还可能会遇到菱形继承的问题。这里我们首先来看一下什么叫做多继承。既然有多继承,自然就有单继承。单继承:所谓单继承,就是指只有一个父类多继承:所谓多继承,就是指有多个父类

菱形继承问题:首先需要说明,菱形继承问题只会在多继承里面才会出现。例如: A和B都继承MindonBase类,假设Base类 里面有一个成员方法, 那么A和B里面都会有这个成员方法,这个时候A和B
两个类又都对这个成员方法进行了修改。接下来让一个C来同时继承A和B,那么 这个时候就会产  Q




迷途 2019/7/23 星期二 19:18:00

迷途 2019/07/23 19:17:59

      13-4与原型相关的方法

      前面已经介绍了JS里面比较有特色的原型对象,也介绍了在JS里面如何创建构造函数或者类,然后通过构造函数和类来实例化出对象。接下来,我们就来看一下JS中和原型对象相关的一- 些方法。

      1. prototype和_ proto_

      prototype是构造函数上面的一个属性,指向一个对象,这个对象是构造函数实例化出来的对象的原型对象。实例化出来的对象可以通过proto_ 来找到自 己的原型对象。

      Let Computer = function(name, price){

      this.name = name ;this.price = price;}

      Computer. prototype. showSth = function(){

      console. log(这是一台${this . name}电脑);

      Let apple = new Computer("苹果",12000);

      console. log(Computer . prototype);//Computer { showSth: [Function }console. log(apple._ proto__ );//Computer { showSth; [Function] }console. log(Computer. prototype === apple._ proto__ );// true



迷途 2019/7/23 星期二 19:18:17

迷途 2019/07/23 19:18:17

2. Object.getPrototypeOf)

Bâ7. Lïẞîi_ proto_ жäE!JXJ EXRIX9N, tEFJlXi Object. getPrototypeOfl) жE# - -↑XJ SgR@XJR

      let Computer = function (name,price)f

      this. name = name;this.price = price;

      Computer . prototype. showSth = function()f

      console.log(' i&- B$íthis. name]Aü );3

      let apple = new Computer("4#", 12000);

      console. log(Object. getPrototypeOf (apple));//Computer ( showSth: [Function] 1console. log(apple._ _proto__ );//Computer f showSth: [Function] ]

      console. log(0bject . getPrototypeOf(apple) === apple._ proto__ );//true



迷途 2019/7/23 星期二 19:18:28

迷途 2019/07/23 19:18:27
-般来讲,对于私有属性,有一个不成文的规定,那就是习惯使用_开头来命名私有属性。这里我们可以看到,由于我们对price属性进行了封装,所以外部无法访问到。

封装后的属性,我们可以将其称之为私有属性。对于外部来讲,私有属性是不可见的,这个我们已经知道了,但是对于内部来讲,私有属性是可见的。这就好比电视机里面的零部件封装后外部无法直接访问到,但是电视机内部是可以使用这个零部件来完成相应的功能的。示例如下:

Let Computer = function (name,price){
this. name = name;Let_ price = price;
this.sayPrice = function(){
console. log(价格为${_ .price} );

}
}
Computer . prototype. showSth = function(){
console. log(这是一台${this . name}电脑~ );

}
Let apple = new Computer("苹果" , 12000);apple. sayPrice();//价格为12000




迷途 2019/7/23 星期二 19:18:38

迷途 2019/07/23 19:18:37

callf9l]:

      let Person = function(name, age)[

      this. name = name;this.age = age;

      Person. prototype.test = function()[

      console. log("this is a test");

let Student = function( name, age , gender, score)f  l

      11 XPersoni Fi/this EäF11this6EE#E

      Person. call(this , name , age);this . gender = gender;this.score. = score;

      let xiejie = new Student("i92", 18,"B" ,100);console. log(xiejie.name);// i$%2N3console. log(xiejie.age);//18 Iconsole. log(xiejie.gender);11#console. log(xiejie. score);//100

      xiejie. test();//TypeError: xiejie,test is not a function

猜你喜欢

转载自www.cnblogs.com/jrzqdlgdx/p/11267513.html