JavaScript | 对象详解
—————————————————————————————————————————————————————————
对象有哪些(导图)
-
内建对象
-
数据封装对象
- Object对象
- Object.prototype
- Array对象
- Function对象
基本包装类型
- Number对象
- Boolean对象
- String对象
-
工具类对象
- Math对象
- Date对象
- RegExp对象
-
全局对象
- Global对象
-
错误对象
- Error对象
-
- 自定义对象
注解:基本包装类型
因为有了基本包装类型,所以js中的基本类型值可以被当做对象来访问。
共同特征:
- 每个包装类型都映射到同名的基本类型
- 在读取模式下访问基本类型值时,就会创建对应的基本包装类型的一个对象,从而方便了数据操作
- 操作基本类型值的语句已经执行完毕,就会立即销毁新创建的包装对象
—————————————————————————————————————————————————————————
Object对象
-
Object对象是Js中所有对象的父级对象,我们创建的所有对象都继承于此
方法:
未归类:
Object.create(): |
指定原型对象和属性创建一个对象 |
Object.defineProperty(): |
给对象添加/修改一个属性并指定该属性的配置 |
Object.defineProperties(): |
在一个对象上添加或修改一个或者多个自有属性,并返回该对象 |
Object.keys(): |
方法会返回一个由给定对象的所有可枚举自身属性的属性名组成的数组,数组中属性名的排列顺序和使用for-in循环遍历该对象时返回的顺序一致(两者的主要区别是for-in还会遍历除一个对象从其原型链上继承到得可枚举的属性) |
Object.getOwnPropertyNames(): |
返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性)组成的数组 |
Object.getOwnPropertyDescriptor(): |
返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)) |
Object.getPrototypeOf(): |
返回指定对象的原型(也就是该对象内部属性[[Prototype]]的值) |
可扩展性方法:
内建对象和自定义对象是显示可扩展的,宿主对象的可扩展性由JavaScript引擎定义。可扩展性的目的是为了将对象锁定,防止外界干扰,通常和对象的属性的可配置的行与可写性配合使用
Object.freeze(): |
冻结一个对象。冻结对象是指那些不能添加新的属性,不能修改已有属性的值,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性的对象。也就是说这个对象永远不能改变的 p.s. 只影响对象本身,不影响从其原型继承来的属性。 |
Object.isFrozen(): |
判断对象是否已经被冻结 |
Object.preventExtensions(): |
阻止对象扩展 |
Object.isExtensible(): |
检测一个对象是否可扩展(是否可以在它上面添加新的属性) |
Object.seal(): |
可以让一个对象密封,并返回被密封之后的对象。密封对象是指那些不能添加新的属性、不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值的对象 p.s. 如果对象的存储器属性具有setter方法,存取器属性将不受影响,仍可以通过属性赋值调用它们 |
Object.isSealed(): |
检测一个对象是否被密封sealed |
var obj = {}; // 检测是否可扩展 console.log(Object.isExtensible(obj)); // 内建对象Date var oTest = new Date(); console.log(Object.isExtensible(oTest)); oTest.x = 1; console.log(oTest.x); // 对象锁定 oTest2 = Object.preventExtensions(oTest); // 证明oTest2与oTest是同一对象,已经不可扩展 console.log(oTest2 === oTest); console.log(Object.isExtensible(oTest2)); // 此时显示y为undefined未定义的 oTest2.y = 1; console.log(oTest2.y); // defineProperty方法会报错,提示不可扩展 // Object.defineProperty(oTest2,'z',{value:1}); // ******************************************************************* // 封闭对象seal() var oTest3 = { x: 1, y: 2 }; var oTest4 = Object.seal(oTest3); // false不可扩展 console.log(Object.isExtensible(oTest3)); // true已经被封闭了 console.log(Object.isSealed(oTest3)); // 自身已有的属性不受影响 oTest3.y = 55; console.log(oTest3.y); // 提示不能将新属性定义为访问器属性 // Object.defineProperty(object,'username',{ // get:function(){ // return 'this is a test'; // } // }); oTest3.z = 111; console.log(oTest3.z); // 已有属性也不会被删除 delete oTest3.x; console.log(oTest3.x); // 检测属性 configurable:false,不可配置 console.log(Object.getOwnPropertyDescriptor(oTest3, 'x')); // ******************************************************************* // 冻结对象freeze() console.log('freeze:'); var oTest5 = { x: 1, y: 2, z: 3 }; oTest6 = Object.freeze(oTest5); // 冻结后检测对象 writable:false,变成了只读属性 console.log(Object.getOwnPropertyDescriptor(oTest6, 'x')); // 检测是否已经被冻结 console.log(Object.isFrozen(oTest6)); // ******************************************************************* // 浅冻结 // 在对象中添加子对象,向子对象添加属性 console.log('Shallow frozen:'); var oTest7 = { internal: {} }; Object.freeze(oTest7); oTest7.internal.x = 1; console.log(oTest7.internal.x); // 在这里只冻结了oTest7的internal,internal对象没有被冻结 console.log(Object.getOwnPropertyDescriptor(oTest7, 'internal')); console.log(Object.getOwnPropertyDescriptor(oTest7.internal, 'x')); // ******************************************************************* // 递归冻结,包括子对象全部冻结 console.log('Deep frozen:'); function deepFreeze(obj) { var prop, propKey; Object.freeze(obj); // 通过for循环来检测是否为子对象,并递归调用 for (propKey in obj) { prop = obj[propKey]; // 如果这个对象没有私有属性||类型不等于Object||已冻结 // 则跳过 - 进入下一循环 if (!obj.hasOwnProperty(propKey) || !(typeof prop === 'object') || Object.isFrozen(prop)) { continue; } deepFreeze(prop); } } var oTest8 = { internal: { x: 1 } } deepFreeze(oTest8); oTest8.internal.y = 2; console.log(oTest8.internal.y); console.log(Object.getOwnPropertyDescriptor(oTest8, 'internal')); console.log(Object.getOwnPropertyDescriptor(oTest8.internal, 'x')); console.log(Object.getOwnPropertyDescriptor(oTest8.internal, 'y')); // ******************************************************************* // 冻结规则: // 1.如果一个对象是可扩展的,那则是非冻结的, // 2.一个不可扩展的对象同时也是一个冻结的对象 var oTest9 = {}; Object.preventExtensions(oTest9); console.log(Object.isFrozen(oTest9)); // 3.空对象和非空对象对比,默认都是不被冻结的,可扩展的 var oTest10 = {}; var oTest11 = { x: 1 }; // 4.空对象禁止扩展后,是被冻结的 Object.preventExtensions(oTest10); console.log('3:' + Object.isFrozen(oTest10)); // 5.非空对象禁止扩展后,不冻结 Object.preventExtensions(oTest11); console.log('4:' + Object.isFrozen(oTest11)); // 6.非空对象删除已有属性后,冻结 delete oTest11.x; console.log('5:' + Object.isFrozen(oTest11)); // 7.如果一个不可扩展的对象拥有一个可写但不可配置的属性,非冻结 // 8.如果一个不可扩展的对象拥有一个不可配置但可写的属性,非冻结 // 9.如果一个不可扩展的对象拥有一个访问器属性,非冻结 // 10.被冻结的对象同样也是被密封的和不可扩展的
检测对象已有属性方法:
- in:包括原型上的
-
hasOwnProperty():仅检测对象自己有的属性
function foo() {} foo.prototype.z = 5; var obj1 = new foo(); obj1.x = 1; obj1.y = 2; console.log('x' in obj1); console.log('y' in obj1); console.log('toString' in obj1); console.log('nonono' in obj1); console.log(obj1.hasOwnProperty('x')); console.log(obj1.hasOwnProperty('z'));
—————————————————————————————————————————————————————————
Object.prototype
-
属性:Object.prototype.constructor:返回一个指向创建了该对象原型的函数引用
方法:
Object.prototype.isPrototypeOf(): |
检测一个对象是否存在于另一个对象的原型链上 |
Object.prototype.propertyIsEnumerable(): |
检测指定的属性名是否是当前对象可枚举的自身属性 |
Object.prototype.toString(): |
返回一个代表该对象的字符串 |
Object.prototype.valueOf(): |
返回的诗this值,即对象本身 |
—————————————————————————————————————————————————————————
Array对象
Array对象图解
-
JavaScript的数组由索引和值组成
-
索引即可以是正整数,也可以是其他类型,但其他类型索引不算在数组长度内
-
当数组索引不连续时,又称为稀疏数组,但相比较连续数组来说,稀疏数组查找元素的速度较慢,未定义部分为undefined
方法:
检测数组方法:
Array.isArray(value) |
检测value是否为数组 |
转换方法:
toString() |
把数组转换为字符串,并返回结果。 |
toLocaleString() |
把数组转换为本地数组,并返回结果。 |
valueOf() |
返回数组对象的原始值。 |
join() |
把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。 |
栈方法:
pop() |
删除并返回数组的最后一个元素 |
push() |
向数组的末尾添加一个或更多元素,并返回新的长度。 |
队列方法:
shift() |
删除并返回数组的第一个元素 |
unshift() |
向数组的开头添加一个或更多元素,并返回新的长度。 |
重排序方法:
reverse() |
颠倒数组中元素的顺序。 |
sort() |
对数组的元素进行排序 |
操作方法:
concat() |
连接两个或更多的数组,并返回结果。 |
slice() |
从某个已有的数组返回选定的元素 |
splice() |
删除元素,并向数组添加新元素。 |
迭代方法:
every() |
如果该函数对每一项都返回true,则true |
filter() |
该函数返回true的项组成数组 |
forEach() |
这个方法没有返回值 |
map() |
返回每次函数调用的结果组成的数组 |
some() |
如果该函数的任一项返回true,则返回true |
位置方法:
Array.indexOf() |
从数组开头向后查找 |
Array.lastIndexOf() |
从数组末尾向前查找 |
其他方法:
toSource() |
返回该对象的源代码。 |
归并方法:
迭代数组的所有项,构建一个最终返回的值
Array.reduce() |
从数组第一项开始,逐个遍历到最后 |
Array.reduceRight() |
从数组最后一项开始遍历 |
以下是手册中没有的为prototype中定义的方法
- Array.map()
- Array.filter()
- Array.reduce()
- Array.reduceRight()
- Array.some()
- Array.every()
- Array.indexOf()
- Array.lastIndexOf()
- Array.isArray()
数组基本操作及常用方法
// Array对象 - 数组 // 创建数组 var colors1 = new Array(); var colors2 = new Array(20); // 指定数组长度,默认为undefined*20,长度20 console.log(colors1.length); console.log(colors2.length); var colors3 = new Array(3); // 如果传参为1个数字则默认为指定长度 console.log(colors3); var colors4 = new Array("1"); // 传入非数值则为数组内容 console.log(colors4); var colors5 = ['1', 'aaa', 21, 3.33]; console.log(colors5); var colors6 = []; // 空数组 console.log(colors6); // p.s.不要使用以下形式创建数组,容易出现歧义,数组项数不确定 // var arr = [1,2,]; // 2或3项 // var arr = [,,,,,]; // 5或6项 // ***************************************************************** // 利用length属性也方便为数组添加元素 console.log(colors5.length); colors5[colors5.length] = "new1"; colors5[colors5.length] = "new2"; console.log(colors5); colors5.length = 2; // 指定长度后如果比之前小,则会移除多余的部分 console.log(colors5); colors5.length = 10; // 扩大length,则填补undefined console.log(colors5); // 数组项的上限是4294967295 var colors7 = new Array(4294967295); // var colors7 = new Array(4294967296); // RangeError: Invalid array length console.log(colors7); // ***************************************************************** // 数组中可以存放所有的变量形式 var arr2 = [1, 2.3, null, true, false, undefined, [1, 2, 3, 4], { x: 1, y: 2, z: 3 }]; console.log(arr2); console.log(arr2[6][1]); console.log(arr2[7].y); // 打印数组长度 console.log(arr2.length); // 引用内容来创建数组 var num = 1; var arr3 = [num, num + 1, num * 2]; console.log(arr3); // 通过构造函数的方式 var arr5 = new Array; // 多个参数时定义的是数组的内容 var arr6 = new Array(1, 2, 3); console.log(arr6); // 任何变量都可以作为索引值,但只有非负整数作为索引时长度才会变化 var arr8 = new Array(); arr8[2.3] = 'a'; arr8[-2333] = 'b'; arr8['c'] = 'b'; // ***************************************************************** // 通过for in取出元素以及元素的索引 for (var i in arr8) { console.log(i + ":" + arr8[i]); } console.log(arr8); console.log(arr8.length); arr8[2] = 'd'; console.log(arr8); console.log(arr8.length); // 压栈弹栈操作 var arr9 = new Array(1, 2, 3); arr9.push(4, 5, 6, 7); console.log(arr9); console.log(arr9.length); arr9.pop(); arr9.pop(); console.log(arr9); console.log(arr9.length); // 在首部加入元素 arr9.unshift(9, 10, 11, 12); console.log(arr9); // 首部弹出元素 arr9.shift(); console.log(arr9); // 删除元素,但删除后长度不变 delete arr9[3]; console.log(arr9); console.log(arr9.length); // 稀疏数组遍历 var arr10 = [1, 2, 3]; arr10[100] = 99; // for-in遍历集成下来的属性 for (var i in arr10) { console.log(i); } // 在forEach()中定义函数体, arr10.forEach(Test); function Test(element, index, array) { console.log("array:" + array + " index:" + index + " element:" + element); } // ***************************************************************** // 检测数组 // instanceof // 缺点:假定只有一个全局执行环境,如果网页包含多个框架,实际存在两个以上不同的全局执行环境时,就有两个以上不同版本的Array构造函数,如果从一个框架向另一个框架传入一个数组,那么传入的数组与第二个框架中原生创建的数组分别具有各自不同的构造函数 console.log(colors5 instanceof Array); // isArray()方法 console.log(Array.isArray(colors2)); // ***************************************************************** // 转换方法 // toString() console.log(colors5.toString()); // valueOf() console.log(colors5.valueOf()); alert(colors5.valueOf()); // alert使用valueOf方法时会在后台调用toString() alert(colors5); // toLocaleString() // 与toString()和valueOf()一样可以返回值 // 调用的同时会创建一个数组值的以逗号分隔的字符串,不同之处在于为了取得每一项的值,调用的是每一项的toLoaclString() var person1 = { toLocaleString: function() { return "111"; }, toString: function() { return "222"; } }; var person2 = { toLocaleString: function() { return "333"; }, toString: function() { return "444"; } }; var people = [person1, person2]; alert(people); // 默认调用的是toString()方法 alert(people.toString()); alert(people.toLocaleString()); // join() 使用不同的分隔符来构建字符串 console.log(colors5.join('||')) // ***************************************************************** // 栈方法 colors5.push('aaa', 'bbb'); // 压栈 console.log(colors5); var item1 = colors5.pop(); // 弹栈 console.log(item1); console.log(colors5); // 队列方法 var len = colors5.push('ccc', 'ddd'); // 压栈 console.log(len); var item2 = colors5.shift(); // 定位到首部并移除,返回移除的元素 console.log(item2); console.log(colors5); colors5.unshift('new'); // 在队列头部推入元素,可以unshift(),pop()联用模拟反向队列 console.log(colors5);
// 通过.map方法返回新函数,在map方法中调用Trans函数,对数组中的每一个元素进行替换操作 var arr = ['abc', 'bcd', 'cde']; res = arr.map(Trans); function Trans(x) { return x.replace(/c/g, '!').toUpperCase(); } console.log(res); // filter var arr = [1, 3, 4, 5, 6, 6, 123, 6547, null, undefined, ""]; res = arr.filter(function(x) { return (x <= 10) && (x != null) && (x != ""); }) console.log(res); // reduce作为累加器,从左到右依次进行返回运算 var arr = [1, 2, 3, 4, 5, 6, 7, 8]; res = arr.reduce(function(a, b) { return a - b; }) console.log(res); res = arr.reduce(function(a, b) { return a * b; }) console.log(res); // reduceRight从右往左 res = arr.reduceRight(function(a, b) { return a - b; }) console.log(res); // every函数检测是否所有的元素都符合要求,有不符合的则返回false var age = [12, 34, 55, 4]; res = age.every(function(x) { return x >= 18; }) console.log(res); // some检测的是否有符合的,有符合的则返回true var age = [12, 34, 55, 4]; res = age.some(function(x) { return x >= 18; }) console.log(res); // 索引 var arr = ['a','b','c','b','d','b','e']; // 第一个索引位 res = arr.indexOf('b'); console.log(res); // 最后一个索引位 res = arr.lastIndexOf('b'); console.log(res); // 索引开始位置 res = arr.indexOf('b',3); console.log(res);
—————————————————————————————————————————————————————————
Date对象
方法
创建日期
Date.parse() |
解析一个字符串,返回所经过的毫秒数 |
Date.UTC() |
解析一个字符串,返回所经过的毫秒数 |
获取当前时间
Date.now() |
返回当前时间的毫秒数 |
继承的方法
toString() |
把时间转换为字符串,并返回结果。不同浏览器结果不同 |
toLocaleString() |
把时间转换为字符串,并返回结果。不同浏览器结果不同 |
valueOf() |
不返回字符串,返回日期的毫秒表示,可以通过比较操作符来比较日期值 |
日期格式转换
toDateString() |
特定于实现的格式显示星期几、月、日和年 |
toTimeString() |
特定于实现的格式显示时、分、秒和时区 |
toLocaleDateString() |
特定于地区的格式显示星期几、月、日和年 |
toLocaleTimeString() |
特定于实现的格式显示时、分、秒 |
toUTCString() |
特定于实现的格式显示完整的UTC日期 |
toGMTString() |
与toUTCString()等价,为了确保向后兼容,建议使用toUTCString |
日期/时间组件方法
Date对象基本操作及常用方法
// 显示当前时间 console.log(Date()); // 显示毫秒数 var d = new Date(138555555550); console.log(d); // 显示填入的时间 var d = new Date(2011, 1, 3); console.log(d); // 传入月日 var d = new Date(10,25); console.log(d); // ********************************************************* // 创建日期 // Date.parse()方法解析一个字符串,返回所经过的毫秒数 console.log(Date.parse("2017-01-01")); // 格式1 console.log(Date.parse("January 1,2017")); // 格式2 console.log(Date.parse("1/1/2017")); // 格式3 console.log(Date.parse("Tue May 25 2004 00:00:00 GMT-0700")); // 格式4 console.log(Date.parse("2004-05-25T00:00:00")); // 格式5 console.log(Date.parse("aaa")); // 对不能表示日期的字符串返回NaN // Date.UTC()方法 console.log(Date.UTC(2000,0)); // 2000年1月,必传的两个参数 console.log(Date.UTC(2000,0,1,2,3,4,5)); // 2000年1月1日2点3分4秒5毫秒 // ********************************************************* // 通过Date.now()获取当前时间 var start = Date.now(); // doSomething(); var stop = Date.now(); result = stop - start; // 通过两次获取当前时间相减得到间隔时间 // p.s.不支持ES5的Date.now()方法的可以使用如下 var start = +new Date(); // doSomething(); var stop = +new Date(); result = stop - start; // ********************************************************* // 日期格式化 var curTime = new Date(); console.log(curTime); console.log(curTime.toDateString()); console.log(curTime.toTimeString()); console.log(curTime.toLocaleDateString()); console.log(curTime.toLocaleTimeString()); console.log(curTime.toUTCString()); console.log(curTime.toGMTString());
—————————————————————————————————————————————————————————
Math对象
属性
方法
abs(x) |
返回数的绝对值。 |
acos(x) |
返回数的反余弦值。 |
asin(x) |
返回数的反正弦值。 |
atan(x) |
以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。 |
atan2(y,x) |
返回从 x 轴到点 (x,y) 的角度(介于 -PI/2 与 PI/2 弧度之间)。 |
ceil(x) |
对数进行上舍入。 |
cos(x) |
返回数的余弦。 |
exp(x) |
返回 e 的指数。 |
floor(x) |
对数进行下舍入。 |
log(x) |
返回数的自然对数(底为e)。 |
max(x,y) |
返回 x 和 y 中的最高值。 |
min(x,y) |
返回 x 和 y 中的最低值。 |
pow(x,y) |
返回 x 的 y 次幂。 |
random() |
返回 0 ~ 1 之间的随机数。 |
round(x) |
把数四舍五入为最接近的整数。 |
sin(x) |
返回数的正弦。 |
sqrt(x) |
返回数的平方根。 |
tan(x) |
返回角的正切。 |
toSource() |
返回该对象的源代码。 |
valueOf() |
返回 Math 对象的原始值。 |
—————————————————————————————————————————————————————————
RegExp对象
方法
匹配方法
exec() |
捕获组匹配 |
test() |
通常匹配 |
实例属性
- global 布尔值,表示是否设置了g标志
- ignoreCase 布尔值,表示是否设置了i标志
- lastIndex 整数,表示开始搜索下一个匹配项的字符位置,从0算起
- multiline 布尔值,表示是否设置了m标志
- source 正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回
RegExp构造函数属性
模式的局限性 - 不支持的特性
- 匹配字符串开始和结尾的\A和\Z锚(但支持以 ^$来匹配字符串的首尾)
- 向后查找 lookbehind(但完全支持向前查找 lookahead)
- 并集和交集类
- 原子组 atomic grouping
- Unicode 支持(单个字符除外 \uFFFF)
- 命名的捕获组(但支持编号的捕获组)
- s(single 单行)和x(free-spacing 无间隔)匹配模式
- 条件匹配
- 正则表达式注释
基本操作
// 通过test()方法检索字符串中的内容,返回true或false var patt1 = new RegExp("r"); var res1 = patt1.test('this is javascript course'); console.log(res1); // 另一种形式 // 加上i表示忽略大小写 patt2 = /Javascript/i; res2 = patt2.test('this is javascript course'); console.log(res2); // 是否包含[]中的字符 res3 = /[abc]/.test('Brlue'); // 加上^表示除了abc之外的 res4 = /[^abc]/.test('Brlue'); // 检测是否包含数字 res5 = /[0-9]/.test('999'); // 检测是否包含字母 res5 = /[a-z]/.test('999'); // 是否出现了以下几个 res5 = /php|javascript|ios/.test('php'); console.log(res3); console.log(res4); console.log(res5); // ************************************************************* // 属性 var patt2 = /[abc]/i; console.log(patt2.global); console.log(patt2.ignoreCase); console.log(patt2.lastIndex); console.log(patt2.multiline); console.log(patt2.source); // ************************************************************* // exec()方法 // 专门为捕获组设计,接受一个参数(要应用模式的字符串),返回包含第一个匹配项信息的数组或null // 在/mom( and dad( and baby)?)?/gi中包含两个捕获组,最内部的捕获组匹配and baby,而包含它的捕获组匹配and dad 或 and dad and baby // 除了返回捕获到的项之外,还返回两个属性input和index,分别为检测的字符串和索引位 var matches = /mom( and dad( and baby)?)?/gi.exec("mom and dad and baby"); console.log(matches); var patt3 = /.at/; var text = "cat,bat,sat,fat"; var matches = patt3.exec(text); console.log(matches); var patt3 = /.at/g; // 全局匹配下多次执行,直到索引不到返回null var matches; do { matches = patt3.exec(text); console.log(matches); } while (matches); // test()方法 // 如line 6 - 22 // ************************************************************* // 继承的方法 var patt4 = new RegExp("/[abc]/", "gi"); console.log(patt4.toString()); console.log(patt4.toLocaleString()); // ************************************************************* // 构造函数属性 var text = "this has been a short summer"; var pattern = /(.)hort/g; // 长属性名 if (pattern.test(text)) { console.log(RegExp.input); console.log(RegExp.leftContext); console.log(RegExp.rightContext); console.log(RegExp.lastMatch); console.log(RegExp.lastParen); console.log(RegExp.multiline); } // 短属性名 if (pattern.test(text)) { console.log(RegExp.$_); console.log(RegExp["$`"]); console.log(RegExp["$'"]); console.log(RegExp["$&"]); console.log(RegExp["$+"]); console.log(RegExp["$*"]); } // ************************************************************* // 存储辅助组 - 自动存放9个以内的匹配的捕获组 if (pattern.test(text)) { console.log(RegExp.$1); }
—————————————————————————————————————————————————————————
Function对象
- 函数是对象,函数名是指针
属性
内部属性
-
arguments - 包含传入函数的所有参数
arguments.callee - 指向拥有arguments的函数的指针,递归调用时代替函数名使用
- this - 引用的是函数据以执行的环境对象
其他属性
- caller - 保存调用当前函数的函数的引用
- length - 保存参数个数
- prototype - 保存所有实例方法
属性使用方法及this详解
// function.length function fun1() {}; function fun2(var1) {}; function fun3(var1, var2) {}; console.log(fun1.length); console.log(fun2.length); console.log(fun3.length); // ******************************************************* // arguments function fun4(num1, num2) { console.log(this); // arguments } function callFun4(num1, num2) { console.log(arguments); // arguments为参数数组 console.log(this); // Window,callFun4是在全局环境下被调用 return fun4.apply(arguments); } callFun4(10, 20); // this - 指向的是调用它的上一级对象 var user1 = "222"; function fun5() { var user2 = "111"; console.log(this.user1); // 222 console.log(this.user2); // undefined console.log(this); // Window } fun5(); // fun5由window对象调用,所以this指向window var oTest = { user: "333", fun6: function() { console.log(this.user); // 333 undefined console.log(this); // Object Window } } oTest.fun6(); // 在oTest中调用,this返回的就是Object var callFun6 = oTest.fun6; callFun6(); // this:Window // 构造函数this // 构造函数 new关键字改变this指向,指向构造函数fun7() // new关键字会创建一个空的对象,然后自动调用一个apply()方法,将this指向这个空对象,这样的话函数内部的this就会被这个空对象替代 function fun7(){ this.user = "444"; console.log(this); // fun7{user:"444";} } var callFun7 = new fun7(); console.log(callFun7.user); // 444 // 带返回值的问题 function fun8(){ this.user = "555"; return {}; // 返回值是对象时,this指向返回的函数 // return function(){}; // return 1; // 返回其他变量类型,则this正常指向fun8 // return null; // 特殊的对象,指向fun8 } var callFun8 = new fun8(); console.log(callFun8.user); // p.s.严格模式下this默认不是Window而是undefined
方法
非继承方法
call() |
在特定作用于中调用函数,等于设置函数体内this对象的值,但需要明确列举传入的参数。扩大作用域 |
apply() |
同上,但不需要逐个列举传入参数,通常用于直接传入arguments对象或包含函数中先接收到的也是一个数组。扩大作用域 |
bind() |
创建一个函数的实例,this值会绑定到传给bind()函数的值 |
方法操作
"use strict"; // **************************************************************** // call(); function fun1(num1, num2) { return num1 + num2; } function callFun1(num1, num2) { return fun1.call(this, num1, num2); // 使用call()方法下必须明确的传入每一个参数, } console.log(callFun1(10, 20)); // apply(); function fun2(num1, num2) { return num1 + num2; } function callFun2(num1, num2) { return fun2.apply(this, arguments); // 使用apply传入this和arguments } console.log(callFun2(10, 20)); // call()和apply()扩展函数作用域 // 扩大作用域的好处:对象不需要与方法有任何耦合关系,不需要将sayColor放到oTest{}对象中再调用了 window.color = "red"; var oTest = { color: "blue" }; function sayColor() { console.log(this); console.log(this.color); } // sayColor(); 严格模式下无法打印window.color sayColor.call(this); sayColor.call(window); sayColor.call(oTest); // this指向oTest // **************************************************************** // bind() 方法 window.color2 = "yellow"; var oTest2 = {color:"green"}; function sayColor2(){ console.log(this); console.log(this.color); } var objectSayColor = sayColor2.bind(oTest2); objectSayColor();
—————————————————————————————————————————————————————————
String对象
字符方法
charAt() |
返回某个位置的字符 |
charCodeAt() |
返回某个位置的字符ASCII码 |
字符串操作方法
concat() |
字符串拼接 |
slice() |
返回子串 |
substring() |
同上,区别见操作 |
substr() |
同上,区别见操作 |
字符串位置方法
indexOf() |
从一个字符串中搜索给定的字符串,返回子串的位置,没有子串返回-1,从头开始 |
lastIndexOf() |
同上,从尾开始 |
特殊方法
trim() |
删除前置及后缀所有空格,返回结果 |
localeCompare() |
比较字符串,返回 1 或 0 或 -1 |
fromCharCode() |
接收一或多个字符编码转化成字符串 |
字符串大小写转换
toLocaleLowerCase() |
把字符串转换为小写。 |
toLocaleUpperCase() |
把字符串转换为大写。 |
toLowerCase() |
把字符串转换为小写。 |
toUpperCase() |
把字符串转换为大写。 |
支持正则对象的模式匹配方法
match() |
找到一个或多个正则表达式的匹配。 |
replace() |
替换与正则表达式匹配的子串。 |
search() |
检索与正则表达式相匹配的值。 |
split() |
把字符串分割为字符串数组。 |
方法操作
"use strict"; // 创建方法 var str = new String("hello,world"); console.log(str); console.log(str.length); // 字符方法 console.log(str.charAt(1)); // 返回某个位置的字符 console.log(str.charCodeAt(1)); // 返回某个位置的字符ASCII码 // 字符串操作方法 var str2 = str.concat("!", "hugh,dong"); // 字符串拼接 console.log(str2); console.log(str2.slice(2)); // 返回n之后的子串 console.log(str2.substring(2)); // 同上 console.log(str2.substr(2)); // 同上 console.log(str2.slice(3, 7)); // 返回 a-b位的子串 console.log(str2.substring(3, 7)); // 同上 console.log(str2.substr(3, 7)); // 返回a位开始数长度b的子串 console.log(str2.slice(-3)); // 返回倒数n个 console.log(str2.substring(-3)); // 返回全部 console.log(str2.substr(-3)); // 返回倒数n个 console.log(str2.slice(3, -4)); // 返回 a-b位的子串 console.log(str2.substring(3, -4)); // 返回开头a个 console.log(str2.substr(3, -4)); // 返回空串 // trim() var str3 = " a a a "; var str4 = str3.trim(); console.log(str4); // ********************************************************************** var myArr = new Array; var str = 'this is a test hello ishello maizi'; var patt = /is/ig; var i = 0; while ((myArr[i] = patt.exec(str)) !== null) { console.log(i + 1 + ':' + myArr[i] + " " + patt.lastIndex); i++; } str = 'this is a testis'; patt = /is/ig; var res = str.match(patt); console.log(res); res = str.search(patt); console.log(res); res = str.replace(patt, '!'); console.log(res); // 将年月日替换为月日年 str = '2017-06-04'; res = str.replace(/(\d{4})-(\d{2})-(\d{2})/, '$2-$3-$1'); console.log(res); // 调用方法,将匹配到的内容替换成为hugh+匹配内容大写 str = 'this is a testis'; res = str.replace(/is/g, func); function func(match) { return 'hugh' + match.toLocaleUpperCase(); } console.log(res); // split // 将匹配到的字符串前后拆分 res = str.split(/\s+/); console.log(res);
—————————————————————————————————————————————————————————
Number对象
属性
- constructor - 返回对创建此对象的 Number 函数的引用。
- MAX_VALUE - 可表示的最大的数。
- MIN_VALUE - 可表示的最小的数。
- NaN - 非数字值。
- NEGATIVE_INFINITY - 负无穷大,溢出时返回该值。
- POSITIVE_INFINITY - 正无穷大,溢出时返回该值。
- prototype - 使您有能力向对象添加属性和方法。
方法
toString() |
把数字转换为字符串,使用指定的基数。 |
toLocaleString() |
把数字转换为字符串,使用本地数字格式顺序。 |
toFixed() |
把数字转换为字符串,结果的小数点后有指定位数的数字。 |
toExponential() |
把对象的值转换为指数计数法。 |
toPrecision() |
把数字格式化为指定的长度。 |
valueOf() |
返回一个 Number 对象的基本数字值。 |
—————————————————————————————————————————————————————————
Boolean对象
基本类型和引用类型的布尔值区别
p.s. 建议不使用引用类型(Boolean对象)
|
写法 |
值 |
typeof判断 |
instanceof Boolean判断 |
基本类型 |
var b = false; |
false |
boolean |
false |
引用类型 |
var b = new Boolean(); |
使用布尔表达式创建时的值都转换为true, var falseObject = new Boolean(false); 此时falseObject的值为true |
object |
true |
—————————————————————————————————————————————————————————
Global对象
-
Global全局对象某种意义上是不存在的,实际上不属于任何其他对象的属性和方法最终都是它的属性和方法。如:isNaN(),isFinite(),parseInt(),parseFloat(),encodeURI(),encodeURIComponent()...
eval()方法 - 执行值中的js代码
p.s. 解释代码字符串能力强大,也很危险,尤其是在执行用户输入数据的情况下,否则可能会造成代码注入
属性
—————————————————————————————————————————————————————————
Error对象
通常使用try/catch/finally来捕获Error错误
Error类型:EvalError / InternalError / RangeError / ReferenceError / SyntaxError / TypeError / URIError
try { // 当调用不存在的notExists(),e.name和e.message存放的错误名称和错误信息 // notExists(); var n = 0; if (n == 0) { // 手动抛出一个错误信息 throw new Error('Throw an error message'); } } catch (e) { console.log(e.name); console.log(e.message); } finally { // finally中的总是被调用 console.log('i am in finally'); } try { notExists(); } catch (e) { // 判断错误的实例化类型 if (e instanceof EvalError) console.log('this is a EvalError'); else if (e instanceof SyntaxError) console.log('this is a SyntaxError'); else if (e instanceof ReferenceError) console.log('this is a ReferenceError'); else console.log('An unknown errorr'); } // 对Error对象重写 function myError(msg) { this.name = "myError'sname"; this.message = msg || "myError'info"; } // 通过Object.create()创建错误原型 myError.prototype = Object.create(Error.prototype); myError.prototype.constructor = myError; try { throw new myError(); } catch (e) { console.log(e.name); console.log(e.message); }
—————————————————————————————————————————————————————————
自定义对象
- 通过var obj = {} 对象字面量法
- 通过var obj = new Object()创建
-
通过函数构造创建对象
p.s. 使用的时候通过new操作符得到对象
用构造器创建对象的时候可以接收参数
构造器函数的首字母最好大写,区别其他的一般函数
- function Person(){}
- var Persion = function(){}
-
构造器属性(constructor property)
- 当我们创建对象的时候,实际上同时也赋予了该对象一种特殊的属性,即构造器属性
- 这个构造器属性实际上是一个指向用于创建该对象的构造器函数的引用
- 通过instanceof操作符可以检测一个对象是否由某个指定的函数构造器创建
-
通过Object.create()创建对象
/*********************************** * 对象字面量 ***********************************/ var oTest = {}; document.write(typeof oTest + "</br>"); var oTest2 = { x: 1, 'y': 2, "z": 3 }; document.write(oTest2.x + " " + oTest2.y + " " + oTest2.z + "</br>"); var oTest3 = { username: 'rog91222', passwd: '123123', person: { firstname: "hugh", lastname: "dong" }, age: 20 } document.write(oTest3.username + " " + oTest3.person.firstname + " " + oTest3.age + "</br>"); /*********************************** * new Object()创建对象 ***********************************/ var oTest4 = new Object(); /*********************************** * 通过构造器函数的形式创建对象 ***********************************/ function funcTest(num1, num2) { this.n1 = num1; this.n2 = num2; } var oTest5 = new funcTest(1, 2); document.write(oTest5.n1 + " " + oTest5.n2 + "</br>"); // 通过instanceof检测是否由函数构造器构造的 document.write(oTest5 instanceof funcTest); document.write("<br>") /*********************************** * 通过Object.create()创建对象 ***********************************/ var oTest6 = Object.create({ x: 1 }); // 不继承任何方法 var oTest7 = Object.create(null); // 创建一个普通的空对象 var oTest8 = Object.create(Object.prototype);