博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
「JavaScript面向对象编程指南」对象
阅读量:4841 次
发布时间:2019-06-11

本文共 7012 字,大约阅读时间需要 23 分钟。

对象的属性名可加上引号,下面三行代码所定义的内容是完全相同的

var hero = { occupation : 1 };var hero = { "occupation" : 1 };var hero = { 'occupation' : 1 };

通常情况下不建议在属性名上加引号,但以下情境就必须加引号:

  • 属性名是JS的保留字之一
  • 属性名包含了除字母数字下划线$以外的字符
  • 属性名以数字开头

总而言之,若属性名不符合JS的变量命名规则就必须加上引号

对象的属性值可以是函数,因为函数本身也是一种数据,在这情况下,称该属性为对象的方法

var person = {    name : 'Sam',    say : function(){        alert('Hi~');    }};

一些程序设计语言中,通常会有索引型数组(键名为数字)和关联型数组(通常以字符串为键值),也叫哈希表或字典

JS中用数组表示索引型数组,用对象表示关联型数组

访问对象的属性可用点号也可用中括号的方式,若访问的属性名不符合变量命名规则或属性名通过变量获取的,就必须使用中括号

对象属性名尽量别加引号,对象属性和方法的访问尽量使用点号

JS是动态类型语言,对象在任何时候都可进行增删改属性,但一些内建对象的一些属性不可改变如(Math.PI)

空对象本身会继承一些属性,ES5中才可以创建一个不继承任何属性的对象

当处于某个对象的方法内部时,可用this关键字访问该对象的属性或方法

JS程序所在的宿主环境一般都会为其提供一个全局对象,而所谓的全局变量不过是该对象的属性罢了

但宿主环境是Web浏览器时,它提供的全局对象是window,另一种获取全局对象的方法(此方法在浏览器外的大多数其他环境也同样有效)是在函数之外使用this关键字

创建对象时,实际同时赋予了该对象一种特殊的属性,即构造器属性,该属性实际上是一个指向用于创建该对象的构造器函数的引用

由于构造器属性所引用的是一个函数,因此我们也可以利用它来创建一个其他新对象

function Hero(name){    this.name = name;}var h = new Hero('Sam');> h.constructor //ƒ Hero(name){this.name = name;}var h2 = new h.constructor('May');> h2.name //May

若对象是通过“对象文本标识法”(字面量形式)创建的,那实际上它就是由内建构造器Object()函数所创建

var obj = {};> obj.constructor //function Object(){ [native code] }

通过instanceof操作符,可测试一个对象是否由某个指定的构造器函数创建

function Hero(){}var h = new Hero()var obj = {}> h instanceof Hero //true> h instanceof Object //true> o instanceof Object //true

改变构造器的默认行为

function Fn(){    this.a = 1;    return {        b:2;    }}> var obj = new Fn()> typeof obj.a //undefined> obj.b //2

在这里,构造器返回的不再是包含属性a的this对象,而是另一个包含属性b的对象

但这也只有在函数返回值是一个对象时才会发生,若返回的是非对象类型时,该构造器会照常返回this

关于对象在构造器函数内如何创建出来,可设想在函数开头有个叫this的变量,这个变量会在函数结束时被返回,像这样

function C(){    // var this = {};    this.a = 1;    //return this;}

对对象进行比较时,当且仅当两个引用指向同一个对象,结果才为true

JS中内建构造器(内建对象)大致可分为三类:

  • 数据封装类对象,Object、Array、Boolean、Number和String
  • 工具类对象,Math、Date、RegExp等
  • 错误类对象

不要去纠结什么是内建对象,什么是内建构造器,实际上它们是一回事,无论函数还是构造器函数,最后都是对象

Object是JS中所有对象的顶级父对象

var o = {};
var o = new Object();
是等价的

o.constructor :返回构造器函数的引用

o.toString : 返回对象的描述字符串
o.valueOf : 返回对象的单值描述信息,通常返回的就是对象本身

toString()方法会在需要用字符串来表示对象的时候被JS内部调用,如alert()或用+拼接时,该对象会调用自身的toString()方法

Array()是个用来构建数组的内建构造函数

var a = [];
var a = new Array();
是等价的
既然数组是由构造器创建,这意味着数组实际上也是对象,所以也继承了Object的所有方法和属性

可以手动设置数组的length属性,若设置的值大于当前数组长度,剩下的会被undefined自动填充,若小于则多出的部分会被移除

1471778-20190320233639018-769853882.png
a.push("Hi")就相当于 a[a.length] = 'Hi',而 a.pop()则与
a.length--的结果相同。

函数是一种特殊的数据类型,实际上它也是对象,函数对象的内建构造器是Function(),此为创建函数的第三种方式但不推荐

函数的constructor属性也是其构造器函数的引用
length属性记录函数声明时参数列表里的参数个数
toString()方法返回的是该函数的源代码,用此方法查看那些内建函数的源码时,只会得到一个字符串[native code]
所以可用此来区分本地方法和自定义方法

JS中每个函数都会有call()和apply()两个方法,可让一个对象“借用”另一对象的方法,这也是种非常简单而实用的代码复用

var obj = {    job:'singer',    say:function (name) {        console.log('my name is ' + name +',I\'m a ' + this.job);    }}obj.say('Sam');var obj2 = {    job:'teacher'}obj.say.call(obj2,'May');obj.say.apply(obj2,['May']); //apply工作方式和call基本相同,唯一不同的是apply要传递数组

调用say()函数的对象方法call()时传递了两个参数,obj2对象和参数

这样一来,当say()被调用时,其中的this就被自动设置成obj2对象的引用
若没有传对象给call()的首参数或传递null,则调用对象将会被默认为全局对象

函数中的arguments是类似数组的对象,和数组的相似之处仅在于也包含了索引和length属性,而sort()、push()等数组方法却没有

但可把arguments转换成数组,这样就可使用各种各样的数组方法了

function f(){    var args = [].slice.call(arguments); //也可使用Array.prototype.slice来调用同一个函数    return args.reverse();}> f(1,2,3,4); //[4,3,2,1]

推断对象类型

数组的 typeof 返回值也为"object",那么如何区分对象与数组?
答案是使用 Object 对象的 toString()方法。这个方法会返回所创建对象的内部类名

> Object.prototype.toString.call({});"[object Object]"> Object.prototype.toString.call([]);"[object Array]"

在这里,toString()方法必须要来自于 Object 构造器的 prototype 属性,直接调用Array 的 toString()方法是不行的,因为在 Array 对象中。这个方法已经出于其他目的被重写

这种推断方法也适用于DOM元素

> Object.prototype.toString.call(document.body); //"[object HTMLBodyElement]"

var b = new Boolean()

所创建的b是一个对象而不是基本数据类型的布尔值
Boolean()构造器创建的对象没有多少实用性,除了来自继承的,自身没有任何属性和方法
不使用new操作符而单独作为一般函数使用时,Boolean()可将一些非布尔值转换为布尔值(效果相当于两次取反操作)

创建的Number对象有三种方法,toFixed()、toPrecision()和toExponential()

var n = new Number(123.45);n.toFixed(1);

在事先未创建Number对象的情况下也可使用这些方法,因为Number对象会在后台自动被创建和销毁

(1234).toExponential(); //"

Number对象自己的toString()方法可带一个参数表示用多少进制

b.toString(16)

基本类型的字符串不是对象,所以不含有任何属性和方法,但当我们将一个基本字符串当作对象使用时,后台会相应的创建String对象,在调用完后又把String对象立即销毁

> 'potato'.length // 6> 'tomato'[0] // "t"

Math.random() 返回 [0,1) 间的某个数,若想获取min和max范围的值,可通过公式

((max - min) * Math.random()) + min

Math.round() 返回最靠近指定值的整数

内建构造器RegExp()来创建正则表达式对象

var reg = new RegExp('J.*t'); //匹配J开头,t结尾,中间包含一个或以上任意字符的字符串var reg = /J.*t/; //字面量形式,正则文本标记法

正则表达式对象拥有的属性:

  • global:默认false,即找到第一个匹配时就停止
  • ignoreCase:是否区分大小写,默认false,区分
  • multiline:是否跨行搜索,默认false,不跨行
  • lastIndex:搜索开始的索引位,默认0
  • source:用于存储正则表达式匹配模式
    前三个属性可用regex修饰符表示,即g、i、m
    除了lastIndex,其他属性在对象创建后都不能再被修改
var reg = new RegExp('J.*t','gmi'); //修饰符无序,传递给构造器后相应的属性就被设为truevar reg = /'J.*t'/gi;

RegExp对象有两种可用于查找匹配内容的方法:test()和exec()

test()返回布尔值
exec()返回数组,匹配的字符串组成的数组

/j.*t/i.exec('Javascript')[0]; //"Javascript"

String对象的IndexOf()和lastIndexOf()方法只能用于纯字符串式子的搜索,若想获得更强大的文本搜索能力就需要使用正则表达式

但String对象也有此能力
String对象的这些方法都能以正则作为参数
match():返回数组,包含匹配内容的数组
search():返回索引,第一个匹配内容所在的索引
replace():将匹配内容替换成指定字符串
split():返回数组,根据字符串或正则,将字符串切割成数组

这四个方法不但能接收正则,也包括字符串,它们会把接收到的字符串参数自动转换成regex对象,就像我们直接传递new RegExp()一样

"test".replace('t', 'r');"test".replace(new RegExp('t'), 'r'); //两者等价

使用字符串的话就不能使用修饰符igm,而且replace()中global修饰符的值将为false,也就是只有第一个匹配的字符串才会被替换,剩下的不会

若正则表达式中分了组(即带括号),则可用$1表示匹配分组的第一组,$2表示第二组,以此类推

var email = 'Jay@qq.com';var name = email.replace(/(.*)@.*/,'$1');> name; //Jay

回调式替换

通过回调,可在替换操作之前实现一些处理逻辑

function replaceCallback(str){    console.log(arguments); //若arguments赋值给一个全局变量,这就能得到replace()传来的参数    return "_" + str.toLowerCase();  //而return的值又会作为替换值}var s = 'JavaScript';s.replace(/(J)(a)/g, replaceCallback);

1471778-20190326000706469-370486423.png

在这里,回调接收到的参数实际有四个
首参数是正则匹配到的内容,尾参数是被搜索的字符串,尾参数之前的一个参数是所匹配内容的索引
剩下的参数则是各个分组
str是形参,replace()函数内部传给replaceCallback函数的参数是实参

Error

程序出现错误时,会抛出一个Error对象,该对象可能由以下几个内建构造器中的一个产生

它们包括EvalError、RangeError、ReferenceError、SyntaxError、TypeError和URIError等,所有这些构造器都继承自Error对象
错误捕获很容易,只需要使用 try 语句后接一个 catch 语句即可

try(){    iDontExist(); //iDontExist()是个未定义的函数} catch (e){    //这里写修复错误的代码或将错误进行反馈}

try 语句及其代码块

catch 语句及其参数变量和代码块

catch 语句的参数 e 实际上是一个 Error 对象,跟其他对象一样,它也

提供一系列有用的方法与属性。遗憾的是,不同的浏览器对于这些方法与属性都有着各自
不同的实现,但其中有两个属性的实现还是基本相同的,那就是 e.name 和 e.message
e.name 是构造当前 Error 对象的构造器名称

也可以用 new Error()或者其他 Error 对象构造器来自定义一个 Error 对象,然后告诉 JS 引擎某个特定的条件,并使用 throw 语句来抛出该对象

try {    var total = maybeExists();    if (total === 0) {        throw new Error('Division by zero!');    } else {        alert(50 / total);    }} catch (e){    alert(e.name + ': ' + e.message);} finally {    alert('Finally!'); //finally是可选的,无论错误是否发生,这里的代码都会执行}

这里抛出的是一般性的错误提示,使用的是 throw new Error('Division by zero!')语句

也可以根据自身的需要来明确错误类型,例如可以利用 throw new RangeError('Division by zero!')语句来抛出该错误
或者不用任何构造器,直接定义一个一般对象抛出:

throw {    name: "MyError",    message: "OMG! Something terrible has happened"}

这样一来,就可以使用自定义的 Error 名,从而解决了浏览器之间由于抛出错误不相同所导致的问题

五种基本数据类型,除了 undefined 和 null 外,其他三个都有相应的构造器 函数

分别是 Number()、String()以及 Boolean(),通过它们我们可以创建出相应的对象,通过将这些基本类型封装成对象,我们就可以在其中集成一些有用的工作方法
Number()、String()以及 Boolean()的调用可分为两种形式:

  • 使用 new 操作符调用 — 用于新建对象。
  • 不使用 new 操作符调用 — 用于将任意值转换成基本数据类型

转载于:https://www.cnblogs.com/Grani/p/10534384.html

你可能感兴趣的文章
项目引入非配置的文件,打成war包后测试报错的可能原因
查看>>
ubuntu更改apache2根目录
查看>>
Hibernate配置属性
查看>>
hibernate.properties
查看>>
那些可能被你忽略的MySQL优化技巧
查看>>
bzoj1034: [ZJOI2008]泡泡堂BNB
查看>>
Android Studio快捷键每日一练(2)
查看>>
atoi函数实现
查看>>
文本文件和二进制文件
查看>>
WCF 实例 —— Android 短信助手 (WCF + Android)
查看>>
C# 读写opc ua服务器,浏览所有节点,读写节点,读历史数据,调用方法,订阅,批量订阅操作...
查看>>
springMVC学习
查看>>
PHP 处理JSON数据
查看>>
SQL Text Literals 文本
查看>>
封装几个有用的函数
查看>>
初识HTML
查看>>
删除目录软链接注意事项
查看>>
一次完整的HTTP事务是怎样一个过程
查看>>
Codeforces Round #440(Div.2)
查看>>
.Net Discovery 系列之一--string从入门到精通(上)
查看>>