| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> JavaScript知识库 -> JS面向对象 -> 正文阅读 |
|
[JavaScript知识库]JS面向对象 |
目录 8.2.7、getOwnPropertyDescriptor 一、构造函数
在
ES6
之前,
JavaScript
不是基于类来创建,而是基于构造函数(
constructor
)和原型链(prototype
)来创建对象。
构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与
new关键字一起使用。我们把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
在
JS
中,使用构造函数时要注意以下两点:
(1)
构造函数用于创建某一类对象,其首字母要大写;
(2)
构造函数要和
new
关键字一起使用才有意义 。
使用示例:
在上面代码中,
new
关键字在创建对象时做以下几件事件:
(1)在内存中创建一个新空对象
(2)让
this
指向到这个新空对象
(3)执行构造函数里面的代码,给这个新对象添加属性和方法。
(4)
返回这个新对象
二、对象成员
在
JavaScript
中,对象成员分为实例成员和静态成员。
2.1、实例成员
实例成员就是构造函数内部通过
this
添加的成员。如上例代码中
name
、
age
、
say
就是实例成员。实例成员只能通过实例化的对象来访问
。
2.2、静态成员
静态成员是在构造函数本身上添加的成员
。如下列代码中
gender
就是静态成员。
静态成员只能
通过构造函数来访问
。
三、instanceof
在面向对象中,可以使用
instanceof
关键字来判断是否为某个对象的实例。
instanceof
是一个
JavaScript
的关键字,用于判断是否为某个对象的实例,如果是则返回true,否则返回
false
。
四、constructor
每一个对象在创建时都会自动拥有一个构造函数的属性
constructor
。
注意:
constructor
属性是继承自原型对象,指向了构造函数的引用。
五、原型对象
构造函数很方便,但是存在内存空间浪费的问题。而
JavaScript
规定,每一个构造函数都有一个prototype属性,指向另一个对象。注意这个
prototype
就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
5.1、原型关系
首先来说一下原型对象,实例对象和构造函数三者之间的关系。下面以示例来进行演示讲解
说明:
(1)
构造函数:用来初始化新创建对象的函数。上例中的
Foo
就是构造函数。它会自动给
构造函数赋予一个叫
prototype
的属性,该属性指向了实例对象的原型对象。
(2)
实例对象:通过
new
创建的对象就是实例对象,如上例中的
f1
就是实例对象,实例
对象可以创建多个并且是独立的。每一个原型对象中都有一个
__proto__
对象。每个
实例对象都有一个
constructor
属性,这个属性是继承自父类,它指向了当前的构造
函数。
(3)
原型对象:
Foo.prototype
?首先要明确以下几点:
(1)
在
JS
中万物皆对象。方法(
Function
)是对象,方法的原型
(
Function.prototype
)是对象。因此它们都会具有对象共有的特点。即:对象
具有属性
__proto__
,可称为隐式原型,一个对象的隐式原型指向构造该对象的
构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方
法。
(2)
方法(Function)
是一个特殊的对象,除了和其他对象一样有上述
__proto__
属性之外,还有自己特有的属性——
原型属性(
prototype
),这个属性是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象)。原型对象也有一个属性,叫做 constructor
,这个属性包含了一个指针,指回原构造函数。
总结:
(1)
构造函数
Foo()
的原型属性
Foo.prototype
指向了原型对象,在原型对象里有共
有的方法,所有构造函数声明的实例(这里是
f1
,
f2
)都可以共享这个方法。
(2)
原型对象
Foo.prototype
保存着实例共享的方法,有一个
constructor
指回构造
函数。
(3)
对象
f1
是
Foo
对象的实例,这个对象有一个
__proto__
属性,指向构造函数的
原型对象,用于访问原型对象的所有方法。
(4)
原型对象的
__proto__
指向的是父级对象的原型对象,例如上例中
Foo.prototype.__proto__
指向是
Object.prototype。
? 5.2、原型属性
本节来说明
prototype
属性的作用。
__proto__
和
constructor
属性是对象所独有,而
prototype
属性是函数所独有的。
但由于在JS 中函数也是一种对象,因此函数也拥有
__proto__
和
constructor
属性。
请看下面的示例:
原型继承的作用:
(1)
JS
继承的机制:通过原型对象实现继承。其实我们平时调用的字符串方法、数组方
法、对象方法、函数方法等都是靠
__proto__
继承而来的。
(2)原型对象的作用就是定义所有实例对象共享的属性和方法。
5.3、原型链
JS
规定,
所有的对象都有自己的原型对象
。
原型链:对象的原型
=>
原型的原型
=>
原型的原型的原型。。。。。。
=> null
根据原型链查找,如果一层一层往上查找,所有对象的原型最终都可以寻找到
Object.prototype
(
Object
构造函数的
prototype
)。
?
总结:所有的对象都继承了
Object.prototype
上的属性和方法。
示例:
读取属性和方法的规则:
JS
引擎会先寻找对象本身的属性和方法,如果找不到就到原型对象上去寻找,这样一层一层寻找,直到找到为止,如果找不到就抛出异常。
5.4、原型总结
总结一下: (1)需要牢记两点:①__proto__ 和 constructor 属性是对象所独有的;② prototype 属性是函数所独有的,由于函数也是一种对象,因此函数也拥有 __proto__ 和 constructor属性。 (2)__proto__ 属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的 __proto__ 属性所指向的那个对象(父对象)里找,一直找,直到 __proto__ 属性的终点 null,再往上找就相当于在 null 上取值,会报错。通过__proto__ 属性将对象连接起来的这条链路即我们所谓的原型链。 (3)prototype 属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即 f1.__proto__ === Foo.prototype。 (4)constructor 属性的含义是指向该对象的构造函数,所有函数最终的构造函数都指向Function。 六、对象创建在 JS 中创建对象有以下 9 种方式。 6.1、对象字面量创建对于对象字面量来创建对象,有以下三种方式 6.1.1、new构造函数创建
6.1.2、字面量创建
6.1.3、create创建
在
ES5
中定义了另种创建对象的方法:从一个实例对象来生成另一个实例对象。使用Object.create() 方法来创建。
说明:
Object
对象的
create()
方法中的参数
person
作为返回实例对象
p
的原型对象,在person中定义的属性和方法,都能被实例
p
继承下来。
6.2、工厂模式
如果创建单个对象,使用字面量的方式来创建是非常方便快捷的。但是,如果我们要创建很多相似的对象,则使用工厂模式是一个比较好的选择。
工厂模式能创建多个类似的对象,但是存在没有解决对象识别的问题。
6.3、构造函数模式可以通过使用构造函数模式来解决工厂模式中存在的无法解决对象识别的问题。
存在问题:使用构造函数模式解决了工厂模式在创建对象是带来的问题,但同时也会产生新问题:在所有实例对象中各自都存有自己的 showName
方法,这样就浪费了资源。
6.4 构造函数拓展模式
构造函数拓展模式解决了构造函数模式中存在的浪费资源的问题。它的设计思想是把方法抽取出来形成一个独立的方法。
构造函数拓展模式解决了系统内存占用的问题,但同时又产生了新的问题:由于函数定义到了对象外部,此时提升为了一个全局函数。是对象中需要有多个方法,是否需要都定义到全局中呢?如果是会污染全局空间,如果不是,那又如何解决?
使用寄生构造函数模式来解决。 6.5 寄生构造函数模式寄生构造函数模式接合了工厂模式和构造函数模式。
创建一个函数,函数体内实例化一个对象,并且将对象返回,在外部的使用
new
来实例化对象。
问题: (1)还定义相同方法,存在浪费资源 (2)instanceof 运算符和 prototype 属性都没有意义 这种模式要尽量避免。 6.6、稳妥构造函数模式
稳妥构造函数模式是指
没有公共属性,并且它的方法也不引用
this
对象
。设计思想是利用闭包来实现。
稳妥构造函数其实是接合闭包来构造对象。p1 就是稳妥对象。 这种创建方式也存在如下问题: (1)浪费内存空间 (2)由于没有使用 new 关键字来创建,所以不能使用 instanceof 和 prototype 属性。 6.7、原型模式原型模式是使用对象的 prototype 属性来创建对象。
原型对象模型是使用对象的
prototype
属性来创建对象的公共属性和方法。它有如下缺点:
当某个实例对象修改原型对象中的属性值后,别的实例对象对应的原型对象中的属性值也会被修改。原因在于引用类型值属性会被所有的实例对象共享并且修改,这也是为什么很少使用原型模式的原因。
6.8、组合模式
组合模式是在原型模式和构造函数模式相接合的一种模式。
注意:改变原型对象的同时,一定要改变该原型对象的
constructor
属性,让它指向当前的构造函数对象 Person
。
6.9、动态组合模式
动态组合模式是将封装的原型对象封装到构造函数中。
在组合模式中, 如果没有调用
new
关键字来创建实例对象,那么对象的引用会发生改变
——
指向的不是构造函数对象,而是 Object
对象。原因是没有实例化,为什么要去初始化呢?
七、继承7.1、原型链继承在原型对象上所有属性和方法,都能被实例所共享。
本质:重写原型对象
,
将一个父对象的属性和方法作为一个子对象的原型对象的属性和方法。
通过上面的代码,绘制原型链图如下:
?原型链方式主要存在以下两个问题的: (1)父类中的实例属性一旦赋值给子类的原型属性,此时这些属性都属于子类的共享属性。 (2)实例化子类型的时候,不能向父类型的构造函数传参。 7.2、构造函数继承构造函数继承也叫伪类继承或经典继承,即在子类的构造函数内部调用父类的构造函数。
7.3、组合继承组合继承接合了原型链继承和构造函数继承的优点。
说明:在组合继承中,重写原型对象,就可以把父类中共享方法继承下来。 八、Object8.1、Object自身方法Object对象方法包括本身的方法和实例方法两种。
Object
对象的实例方法就是在
Object
对象的
prototype
原型对象上定义的方法。
下面我们重点来讲
Object
对象本身的方法:
?示例:
说明:
(1)
keys()
返回可枚举的属性
(2)getOwnPropertyNames()
返回不可枚举和枚举的属性名都能获取
8.2、Object实例方法8.2.1、valueOfObject.prototype.valueOf() 这个方法是返回当前对象的值,默认情况返回对象本身。
8.2.2、toString
Object.prototype.toString()
方法会返回一个对象的字符串形式,默认返回类型字符串。
8.2.3、toLocaleString
Object.prototype.toLocaleString()
方法和
Object.prototype.toString()
方法作用一样。
toString()
是国际标准,而
toLocaleString()
是以区域为标准。下面以日期对象为例来进行说明。
8.2.4、isPrototypeOf
Object.prototype.isPrototypeOf()
方法是用来判断该对象是否是另一个对象的原型。
8.2.5、hasOwnProperty
Object.prototype.hasOwnProperty()
方法接收一个字符串作为参数,返回一个布尔值。表示该实例对象自身是否具有该属性,继承来的属性返回为false
。
8.2.6、propertyIsEnumerable
Object.prototype.propertyIsEnumerable()
方法用于判断某个属性是否可以遍历。只能判断实例对象本身的属性,对于继承来的属性和设置不可枚举的属性一律返回false
。
可枚举即可遍历
。
8.2.7、getOwnPropertyDescriptor
Object.getOwnPropertyDescriptor()
方法可以获取属性描述对象。它有两个参数:第一个参数是目标对象,第二个参数是目标对象的属性名称。
8.2.8、defineProperty
Object.defineProperty()
方法允许我们去改变属性描述对象,如定义或修改一个属性。方法执行后会返回修改后的对象。
Object.defineProperty()
方法有三个参数:第一个参数是属性所在对象,第二个参数是属性名,第三个参数是属性描述对象。
8.2.9、defineProperties
Object.defineProperties()
方法的作用和
Object.defineProperty()
方法功能一样,但是它可以对多个属性进行设置。
Object.defineProperties()
方法有两个参数:第一个参数是属性所在对象,第二个参数是属性描述对象。
|
|
JavaScript知识库 最新文章 |
ES6的相关知识点 |
react 函数式组件 & react其他一些总结 |
Vue基础超详细 |
前端JS也可以连点成线(Vue中运用 AntVG6) |
Vue事件处理的基本使用 |
Vue后台项目的记录 (一) |
前后端分离vue跨域,devServer配置proxy代理 |
TypeScript |
初识vuex |
vue项目安装包指令收集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 9:35:12- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |