————————————————————————————————————————————
对象:JavaScript是基于原型的语言,没有Class,所以将函数作为类
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
面向对象术语
- 对象:属性的无序集合,每个属性存放一个原始值、对象和函数
- 类:每个对象都由类定义,类不仅要定义对象的接口(开发者访问的属性和方法),还要定义对象的内部工作(使属性和方法发挥作用的代码)
- 实例:程序使用类创建对象时,生成的对象叫做类的实例。每个实例的行为相同,但实例处理一组独立的数据。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
四种基本能力
- 封装:把相关的信息(无论数据或方法)存储在对象中的能力
- 聚集:把一个对象存储在另一个对象内的能力
- 继承:由另一个类(或多个类)得来类的属性和方法的能力
- 多态:编写能以多种方法运行的函数或方法的能力
————————————————————————————————————————————
内建对象
-
数据封装对象
-
Object对象
- Object对象是Js中所有对象的父级对象,我们创建的所有对象都继承于此
-
方法:
- Object.create():指定原型对象和属性创建一个对象
- Object.defineProperty():给对象添加/修改一个属性并指定该属性的配置
- Object.defineProperties():在一个对象上添加或修改一个或者多个自有属性,并返回该对象
- Object.keys():方法会返回一个由给定对象的所有可枚举自身属性的属性名组成的数组,数组中属性名的排列顺序和使用for-in循环遍历该对象时返回的顺序一致(两者的主要区别是for-in还会遍历除一个对象从其原型链上继承到得可枚举的属性)
- Object.getOwnPropertyNames():返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性)组成的数组
- Object.getOwnPropertyDescriptor():返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性))
- Object.getPrototypeOf():返回指定对象的原型(也就是该对象内部属性[[Prototype]]的值)
- Object.freeze():冻结一个对象。冻结对象是指那些不能添加新的属性,不能修改已有属性的值,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性的对象。也就是说这个对象永远不能改变的
- Object.isFrozen():判断对象是否已经被冻结
- Object.preventExtensions():阻止对象扩展
- Object.isExtensible():检测一个对象是否可扩展(是否可以在它上面添加新的属性)
- Object.seal():可以让一个对象密封,并返回被密封之后的对象。密封对象是指那些不能添加新的属性、不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值的对象
- Object.isSealed():检测一个对象是否被密封sealed
-
1 var obj = {}; 2 // 检测是否可扩展 3 console.log(Object.isExtensible(obj)); 4 // 内建对象Date 5 var oTest = new Date(); 6 console.log(Object.isExtensible(oTest)); 7 oTest.x = 1; 8 console.log(oTest.x); 9 // 对象锁定 10 oTest2 = Object.preventExtensions(oTest); 11 // 证明oTest2与oTest是同一对象,已经不可扩展 12 console.log(oTest2 === oTest); 13 console.log(Object.isExtensible(oTest2)); 14 // 此时显示y为undefined未定义的 15 oTest2.y = 1; 16 console.log(oTest2.y); 17 // defineProperty方法会报错,提示不可扩展 18 // Object.defineProperty(oTest2,'z',{value:1}); 19 // ******************************************************************* 20 // 封闭对象seal() 21 var oTest3 = { x: 1, y: 2 }; 22 var oTest4 = Object.seal(oTest3); 23 // false不可扩展 24 console.log(Object.isExtensible(oTest3)); 25 // true已经被封闭了 26 console.log(Object.isSealed(oTest3)); 27 // 自身已有的属性不受影响 28 oTest3.y = 55; 29 console.log(oTest3.y); 30 // 提示不能将新属性定义为访问器属性 31 // Object.defineProperty(object,'username',{ 32 // get:function(){ 33 // return 'this is a test'; 34 // } 35 // }); 36 oTest3.z = 111; 37 console.log(oTest3.z); 38 // 已有属性也不会被删除 39 delete oTest3.x; 40 console.log(oTest3.x); 41 // 检测属性 configurable:false,不可配置 42 console.log(Object.getOwnPropertyDescriptor(oTest3, 'x')); 43 // ******************************************************************* 44 // 冻结对象freeze() 45 console.log('freeze:'); 46 var oTest5 = { x: 1, y: 2, z: 3 }; 47 oTest6 = Object.freeze(oTest5); 48 // 冻结后检测对象 writable:false,变成了只读属性 49 console.log(Object.getOwnPropertyDescriptor(oTest6, 'x')); 50 // 检测是否已经被冻结 51 console.log(Object.isFrozen(oTest6)); 52 // ******************************************************************* 53 // 浅冻结 54 // 在对象中添加子对象,向子对象添加属性 55 console.log('Shallow frozen:'); 56 var oTest7 = { 57 internal: {} 58 }; 59 Object.freeze(oTest7); 60 oTest7.internal.x = 1; 61 console.log(oTest7.internal.x); 62 // 在这里只冻结了oTest7的internal,internal对象没有被冻结 63 console.log(Object.getOwnPropertyDescriptor(oTest7, 'internal')); 64 console.log(Object.getOwnPropertyDescriptor(oTest7.internal, 'x')); 65 // ******************************************************************* 66 // 递归冻结,包括子对象全部冻结 67 console.log('Deep frozen:'); 68 69 function deepFreeze(obj) { 70 var prop, propKey; 71 Object.freeze(obj); 72 // 通过for循环来检测是否为子对象,并递归调用 73 for (propKey in obj) { 74 prop = obj[propKey]; 75 // 如果这个对象没有私有属性||类型不等于Object||已冻结 76 // 则跳过 - 进入下一循环 77 if (!obj.hasOwnProperty(propKey) || !(typeof prop === 'object') || Object.isFrozen(prop)) { 78 continue; 79 } 80 deepFreeze(prop); 81 } 82 } 83 var oTest8 = { 84 internal: { 85 x: 1 86 } 87 } 88 deepFreeze(oTest8); 89 oTest8.internal.y = 2; 90 console.log(oTest8.internal.y); 91 console.log(Object.getOwnPropertyDescriptor(oTest8, 'internal')); 92 console.log(Object.getOwnPropertyDescriptor(oTest8.internal, 'x')); 93 console.log(Object.getOwnPropertyDescriptor(oTest8.internal, 'y')); 94 // ******************************************************************* 95 // 冻结规则: 96 // 1.如果一个对象是可扩展的,那则是非冻结的, 97 // 2.一个不可扩展的对象同时也是一个冻结的对象 98 var oTest9 = {}; 99 Object.preventExtensions(oTest9); 100 console.log(Object.isFrozen(oTest9)); 101 // 3.空对象和非空对象对比,默认都是不被冻结的,可扩展的 102 var oTest10 = {}; 103 var oTest11 = { x: 1 }; 104 // 4.空对象禁止扩展后,是被冻结的 105 Object.preventExtensions(oTest10); 106 console.log('3:' + Object.isFrozen(oTest10)); 107 // 5.非空对象禁止扩展后,不冻结 108 Object.preventExtensions(oTest11); 109 console.log('4:' + Object.isFrozen(oTest11)); 110 // 6.非空对象删除已有属性后,冻结 111 delete oTest11.x; 112 console.log('5:' + Object.isFrozen(oTest11)); 113 // 7.如果一个不可扩展的对象拥有一个可写但不可配置的属性,非冻结 114 // 8.如果一个不可扩展的对象拥有一个不可配置但可写的属性,非冻结 115 // 9.如果一个不可扩展的对象拥有一个访问器属性,非冻结 116 // 10.被冻结的对象同样也是被密封的和不可扩展的
-
Object.prototype
- 属性:Object.prototype.constructor:返回一个指向创建了该对象原型的函数引用
-
方法:
- Object.prototype.isPrototypeOf():检测一个对象是否存在于另一个对象的原型链上
- Object.prototype.propertyIsEnumerable():检测指定的属性名是否是当前对象可枚举的自身属性
- Object.prototype.toString():返回一个代表该对象的字符串
- Object.prototype.valueOf():返回的诗this值,即对象本身
- Number对象
- Boolean对象
- Array对象
- Function对象
-
String对象
-
支持正则对象的方法
- search
- match
- replace
- split
-
-
1 var myArr = new Array; 2 var str = 'this is a test hello ishello maizi'; 3 var patt = /is/ig; 4 var i = 0; 5 while ((myArr[i] = patt.exec(str)) !== null) 6 { 7 console.log(i + 1 + ':' + myArr[i] + " " + patt.lastIndex); 8 i++; 9 } 10 11 str = 'this is a testis'; 12 patt = /is/ig; 13 var res = str.match(patt); 14 console.log(res); 15 16 res = str.search(patt); 17 console.log(res); 18 19 res = str.replace(patt, '!'); 20 console.log(res); 21 22 // 将年月日替换为月日年 23 str = '2017-06-04'; 24 res = str.replace(/(d{4})-(d{2})-(d{2})/, '$2-$3-$1'); 25 console.log(res); 26 27 // 调用方法,将匹配到的内容替换成为hugh+匹配内容大写 28 str = 'this is a testis'; 29 res = str.replace(/is/g, func); 30 31 function func(match) 32 { 33 return 'hugh' + match.toLocaleUpperCase(); 34 } 35 console.log(res); 36 37 // split 38 // 将匹配到的字符串前后拆分 39 res = str.split(/s+/); 40 console.log(res);
-
工具类对象
- Math对象
-
Date对象
1 // 显示当前时间 2 console.log(Date()); 3 // 显示毫秒数 4 var d = new Date(138555555550); 5 console.log(d); 6 // 显示填入的时间 7 var d = new Date(2011, 1, 3); 8 console.log(d); 9 // 传入月日 10 var d = new Date(10,25); 11 console.log(d); 12 // Date提供的方法 13 console.log(Date.now()); // 自1970年至今所经过的毫秒数 14 console.log(Date.parse("2017-01-01")); // 解析一个字符串,返回所经过的毫秒数 15 // ...
-
RegExp对象
1 // 通过test()方法检索字符串中的内容,返回true或false 2 var patt1 = new RegExp("r"); 3 var res1 = patt1.test('this is javascript course'); 4 console.log(res1); 5 // 另一种形式 6 // 加上i表示忽略大小写 7 patt2 = /Javascript/i; 8 res2 = patt2.test('this is javascript course'); 9 console.log(res2); 10 // 是否包含[]中的字符 11 res3 = /[abc]/.test('Brlue'); 12 // 加上^表示除了abc之外的 13 res4 = /[^abc]/.test('Brlue'); 14 // 检测是否包含数字 15 res5= /[0-9]/.test('999'); 16 // 检测是否包含字母 17 res5= /[a-z]/.test('999'); 18 // 是否出现了以下几个 19 res5= /php|javascript|ios/.test('php'); 20 console.log(res3); 21 console.log(res4); 22 console.log(res5);
-
错误对象
-
Error对象
- 通常使用try/catch/finally来捕获Error错误
-
Error类型
- EvalError
- InternalError
- RangeError
- ReferenceError
- SyntaxError
- TypeError
- URIError
1 try 2 { 3 // 当调用不存在的notExists(),e.name和e.message存放的错误名称和错误信息 4 // notExists(); 5 var n = 0; 6 if (n == 0) 7 { 8 // 手动抛出一个错误信息 9 throw new Error('Throw an error message'); 10 } 11 } 12 catch (e) 13 { 14 console.log(e.name); 15 console.log(e.message); 16 } 17 finally 18 { 19 // finally中的总是被调用 20 console.log('i am in finally'); 21 } 22 23 try 24 { 25 notExists(); 26 } 27 catch (e) 28 { 29 // 判断错误的实例化类型 30 if (e instanceof EvalError) 31 console.log('this is a EvalError'); 32 else if (e instanceof SyntaxError) 33 console.log('this is a SyntaxError'); 34 else if (e instanceof ReferenceError) 35 console.log('this is a ReferenceError'); 36 else 37 console.log('An unknown errorr'); 38 } 39 // 对Error对象重写 40 function myError(msg) 41 { 42 this.name = "myError'sname"; 43 this.message = msg || "myError'info"; 44 } 45 // 通过Object.create()创建错误原型 46 myError.prototype = Object.create(Error.prototype); 47 myError.prototype.constructor = myError; 48 try 49 { 50 throw new myError(); 51 } 52 catch (e) 53 { 54 console.log(e.name); 55 console.log(e.message); 56 }
-
自定义对象
- 通过var obj = {} 对象字面量法
- 通过var obj = new Object()创建
-
通过函数构造创建对象
p.s. 使用的时候通过new操作符得到对象
用构造器创建对象的时候可以接收参数
构造器函数的首字母最好大写,区别其他的一般函数
- function Person(){}
- var Persion = function(){}
-
构造器属性(constructor property)
- 当我们创建对象的时候,实际上同时也赋予了该对象一种特殊的属性,即构造器属性
- 这个构造器属性实际上是一个指向用于创建该对象的构造器函数的引用
- 通过instanceof操作符可以检测一个对象是否由某个指定的函数构造器创建
- 通过Object.create()创建对象
1 /*********************************** 2 * 对象字面量 3 ***********************************/ 4 var oTest = {}; 5 document.write(typeof oTest + "</br>"); 6 var oTest2 = { x: 1, 'y': 2, "z": 3 }; 7 document.write(oTest2.x + " " + oTest2.y + " " + oTest2.z + "</br>"); 8 var oTest3 = { 9 username: 'rog91222', 10 passwd: '123123', 11 person: { 12 firstname: "hugh", 13 lastname: "dong" 14 }, 15 age: 20 16 } 17 document.write(oTest3.username + " " + oTest3.person.firstname + " " + oTest3.age + "</br>"); 18 /*********************************** 19 * new Object()创建对象 20 ***********************************/ 21 var oTest4 = new Object(); 22 /*********************************** 23 * 通过构造器函数的形式创建对象 24 ***********************************/ 25 function funcTest(num1, num2) { 26 this.n1 = num1; 27 this.n2 = num2; 28 } 29 var oTest5 = new funcTest(1, 2); 30 document.write(oTest5.n1 + " " + oTest5.n2 + "</br>"); 31 // 通过instanceof检测是否由函数构造器构造的 32 document.write(oTest5 instanceof funcTest); 33 document.write("<br>") 34 /*********************************** 35 * 通过Object.create()创建对象 36 ***********************************/ 37 var oTest6 = Object.create({ x: 1 }); 38 // 不继承任何方法 39 var oTest7 = Object.create(null); 40 // 创建一个普通的空对象 41 var oTest8 = Object.create(Object.prototype);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
对象特性
-
原型(prototype)
- 通过对象字面量的形式创建,则使用object.prototype作为它们的原型。
- 通过new和构造函数创建,则使用构造函数的prototype作为它们的原型。
-
如果通过Object.create()创建,使用第一个参数(或null)作为它们的原型
var obj = Object.create({ x: 1 });
- 类(class)
- 扩展标记(extensible flag)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
对象的结构
- 声明对象obj,对象有2个属性 x=1,y=2,每个属性都有对应的属性特性,对象也有3个对象特性
-
对象的原型链:
如图所示,当在对象中找不到属性z时,会向方法的原型查找,继续向对象的原型查找,直到顶层null位置。
每个对象都和另外一个对象关联,就构成了一个原型链,每一个对象都从原型继承属性。
<<test.js>>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
检测对象上是否有某个属性
- in(包括原型上的)
-
hasOwnProperty(仅检测对象自己有的属性)
1 function foo() {} 2 foo.prototype.z = 5; 3 var obj1 = new foo(); 4 obj1.x = 1; 5 obj1.y = 2; 6 console.log('x' in obj1); 7 console.log('y' in obj1); 8 console.log('toString' in obj1); 9 console.log('nonono' in obj1); 10 console.log(obj1.hasOwnProperty('x')); 11 console.log(obj1.hasOwnProperty('z'));
————————————————————————————————————————————
属性
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
数据属性:每个属性有4个描述行为的特性:
- [writable]:是否能修改属性的值
- [enumerable]:是否通过for in 循环返回属性(是否可以被枚举)
- [configurable]:是否能通过delete删除,能否修改属性的特性,能否修改访问器属性
- [value]:包含这个属性的数据值,读取属性值的时候从这个位置读取。默认值为undefined
存取器属性
- get:获取属性的值
- set:设置属性的值
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
属性操作
p.s. 正常属性名可以放在""''或不放引号内,但如果包含特殊字符、保留字、数字开头,必须放在引号之间
- 访问属性
- 添加属性
- 修改属性
- 删除属性
- 遍历属性
1 var person = 2 { 3 fName : 'hugh', 4 lName : 'dong', 5 age : 20 6 }; 7 // 通过.或[]来实现查询属性 8 console.log(person.fName); 9 console.log(person['lName']); 10 console.log(person["age"]); 11 // 如果属性不确定,需要使用[]来读取属性,此处key不能加引号 12 var key = 'fName'; 13 console.log(person[key]); 14 // 在对象内部通过this获取属性 15 function PersonInfo(fName, lName, age) 16 { 17 this.firstName = fName; 18 this.lastName = lName; 19 this.year = age; 20 } 21 var person1 = new PersonInfo('wang', 'er', 30); 22 console.log(person1.firstName); 23 console.log(person1.lastName); 24 console.log(person1.year); 25 // 添加属性 26 var obj = {}; 27 obj.userName = 'username'; 28 obj.passwd = '123456'; 29 obj['permissions'] = 'admin'; 30 console.log(obj.userName); 31 console.log(obj.passwd); 32 console.log(obj.permissions); 33 // 修改属性 34 obj.passwd = '123.com'; 35 console.log(obj.passwd); 36 // 删除属性,删除后再打印该属性为undefined 37 // p.s.delete只能删除自身的属性,不能删除集成的属性 38 // 要删除继承属性,只能从定义它的属性的原型对象上删除它,会影响到所以继承这个原型的对象 39 // delete只是断开属性和宿主对象的联系,而不会去操作属性的属性 40 delete obj.permissions; 41 console.log(obj.permissions); 42 // 遍历属性 43 // i存放的是属性名称,obj[i]存放的是属性值 44 for (var i in obj) 45 { 46 console.log(i + ":" + obj[i]); 47 } 48 // 对象中有方法 49 var obj1 = 50 { 51 user : '111', 52 pass : '222', 53 sayHi : function (x) 54 { 55 return this.user + x + 1; 56 } 57 } 58 console.log(obj1.sayHi(3));