目录
2.3 forEach(返回值undefined)... 4
2.6 filter(由符合条件的成员组成新数组)... 6
2.9 reduce与reduceRight(累加方法)... 8
3.2 bind与(call或apply)的区别... 10
5.2定义特性(Object.defineProperty)... 18
5.3.1判断自身属性(hasOwnProperty)... 21
5.3.2获取属性名称(0bject.getOwnPropertyNames) 22
5.3.3查看属性特性(Object.getOwnPropertyDescriptor())... 22
7.1对象禁拓(Object.preventExtensions)... 24
1. JSON语法
1.1JSON—parse/stringify
将json字符串解析成js对象的
1.使用方式: parse(str, fn) / stringify (str, fn)
str处理的字符串
fn回调函数
返回值表示这次处理的结果
第一个参数表示属性名称
第二个参数表示属性值
2.this指向当前遍历的对象
3.是从叶子节点到根节点的方向遍历的,从内部向外部遍历的 / 外到内
var str = '{"a":1,"b":"2","c":{ "d":4 }}';
//从叶子节点向根节点遍历的,由内到外
//解析成对象
var obj = JSON.parse(str, function (key, value) {
// console.log(arguments, this);//遍历顺序:a-b-d-c
//如果是字符串转成数字,将其转换
if (typeof value === 'string') {
return +value }
return value});
console.log(obj);
2.数组
2.1判断数组
第一种方式判断对象类型是数组
Object.prototype.toString.call(obj)
第二种方式判断构造函数是否是Array
obj.constructor === Array
第三种方式判断是否是Array的实例化对象
obj instanceof Array
第四种方式判断数组的静态方法(只能通过类来访问)isArray
Array.isArray(obj)
var arr = [];var obj = {};
//一:判断对象类型:Object.prototype.toString.call(obj)
console.log(Object.prototype.toString.call(arr));//[object Array]
console.log(Object.prototype.toString.call(obj));//[object Object]
//二:判断构造函数obj.constructor === Array
console.log(arr.constructor === Array);//true
console.log(obj.constructor === Array);//false
//三:判断 Array的实例化对象:obj instanceof Array
console.log(arr instanceof Array);//true
console.log(obj instanceof Array);//false
//四:判断数组的静态方法isArray:Array.isArray(obj)
console.log(Array.isArray(arr));//true
console.log(Array.isArray(obj));//false
2.2获取数组索引值
ES5为数组拓展了两个方法: indexOf, lastIndexOf来获取数组成员的索引值
参数就是这个成员
返回值就是索引值,
如果成员存在,返回索引值(大于等于0)
如果成员不存在,返回-1
查找成员的时候,不会做数据类型的转换,是真正的全等查找
indexOf是从前向后查找的
lastIndexOf是从后向前查找的
Array.prototype.indexOf = function (item) {//lastIndexOf
//遍历数组
for (var i = this.length; i > 0; i--) {
//判断参数是否与成员全等
if (item === this[i]) {
return i; //找到了就返回i
}
}
return -1; }//没有找到返回-1
var result = arr.indexOf(2);
alert(result)
2.3 forEach(返回值undefined)
作用:
用来代替for循环,遍历数组,是数组遍历器方法,并没有移除循环,而是将循环封装在遍历器方法forEach的内部
参数:
回调函数
三个参数:成员值、索引值、原数组
this指向window
返回值对foreach方法执行结果无影响
forEach方法返回值始终是undefined
jQuery提供另一个类似方法,叫each, 区别是each回调函数的第一个参数是索引值 ,第二个参数是成员值
2.4 map(返回值有意义)
作用:
遍历数组并映射结果,与forEach非常类似, 区别是它的返回值有意义
参数是回调函数
三个参数:成员值,索引值,原数组
this指向window
返回值是map方法执行的结果,数组的成员
map方法返回值是一个新数组,每一个成员就是每一次遍历成员时,回调函数的返回值
//map:返回第一个汉字//作用:映射一个新数组
var result = f4.map(function (item, index, arr) {
console.log(item, index, arr);
return item.slice(0, 1) })//返回第一个汉字
console.log(222, result);
//👆222["小", "无", "阿", "张"]//得到的是新数组不影响原数组
//实现map方法(ie可用)
if (!Array.prototype.map) {//没有改方法就拓展一个
Array.prototype.map = function (callback) {
//定义返回的结果
var result = [];
for (var i = 0; i < this.length; i++) {
//执行回调函数,存储结果
result.push(callback(this[i], i, this)) }
return result }}//返回结果
//map:返回第一个汉字 //作用:映射一个新数组
var result = f4.map(function (item, index, arr) {
console.log(item, index, arr);
// return item//小沙比--无敌那--阿飞--张三
// return item[0]//ie不支持索引值方式获取成员
return item.slice(0, 1) })//返回第一个汉字
alert(result.join('--')); //小--无--阿--张
2.5 fill(填充数组的方法)
作用:
我们通过new Array(len), 或者Array(len)创建的数组只有长度,没有成员,所以我们不能用迭代器方法(如forEach, map等等)遍历,为了遍历数组,我们可以向数组中填充成员
参数:
填充的成员,即使是函数也不会执行。
返回值:
原数组
//实现fill
var arr = new Array(5)
if (!Array.prototype.fill) {
Array.prototype.fill = function (item) {//拓展
//遍历成员
for (var i = 0; i < this.length; i++) {
this[i] = item; } //设置成员
return this}} //返回数组
var result = arr.fill(1)
console.log(result); //[1, 1, 1, 1, 1]
var arr = new Array(5);//5:表示5个成员
// console.log(arr, arr.length);// [empty × 5] 5
arr.fill(1); //填充成员,让遍历可以执行//填充了5个1
arr.forEach(function (item, index) { //遍历
console.log(222, item, index); })//没有成员的就不执行,
var result = arr.fill(1)
console.log(result);//[1, 1, 1, 1, 1]
2.6 filter(由符合条件的成员组成新数组)
实现对数组的过滤
使用方式跟forEach一样
参数:
回调函数
三个参数:成员值,索引值,原数组,
返回值:过滤的条件
filter方法返回值是由符合条件的成员组成的新数组
var f4 = ['小沙比', '无敌那', '阿飞小', '张三'];//找出带有小字的成员
var result = f4.filter(function (item, index, arr) {
console.log(this, arguments);//指向window
return item.indexOf('小') >= 0; }) //包含小字
console.log(result);//["小沙比", "阿飞小"]
2.7 some(断言方法)
数组的断言方法:
判断数组中是否有些成员满足条件
使用方式跟forEach一样
参数:
回调函数:fn(item,index,arr)
成员值,索引值,原数组
返回值:
就是判断的依据
some方法返回值
true:至少有一个满足条件
false:一个都不满足条件
some对true敏感,遇到一个满足条件的成员,就停止执行。
var f4 = ['小沙比', '无敌那', '阿小飞', '张三'];
if (!Array.prototype.some) {//实现some方法
Array.prototype.some = function (callback) { //拓展
//遍历数组
for (var i = 0; i < this.length; i++) {
//根据callback执行的结果判断是否继续查找
if (callback(this[i], i, this)) {
return true; } }//有满足条件的
return false; } }
//至少有一个成员,名字中包含 "小"(不是开头,是包含)
var result = f4.some(function (item, index, arr) {
// console.log(arguments, this);
console.log(item)
return item.indexOf('小') > 0; })//成员包含 “小”字
console.log(result);
2.8 every(断言方法)
数组的断言方法:
判断数组中是否有些成员满足条件
使用方式跟forEach一样
参数:
回调函数:fn(item,index,arr)
成员值,索引值,原数组
返回值:
就是判断的依据
every方法返回值
true:全部成员都满足条件
false:至少有一个成员满足条件
every对false敏感,遇到一个不满足条件的成员,停止遍历
if (!Array.prototype.every) {
Array.prototype.every = function (callback) {
for (var i = 0; i < this.length; i++) {
if (!callback(this[i], i, this)) {
return false; } } //有一个成员不满足f条件,返回alse
return true; } }
var f4 = ['小沙比', '无敌那', '小飞', '秦始皇不拉几张三'];
//每一个成员至少俩个汉字//必须全部满足
var result = f4.every(function (item, index, arr) {
console.log(this, arguments);
return item.length >= 2; }) //判断成员汉族个数
console.log(result);//true
2.9 reduce与reduceRight(累加方法)
1.累加方法:
reduce是 从前向后累加
reduceRight是从后向前累加
对所有成员逐一处理, 并将结果返回
2.参数:
回调函数的参数:
四个参数:上一 次累积的结果,当前成员值, 当前索引值,原数组
3.返回值:
就是当次累积的结果,会在下一次执行的时候,作为第一个参数传递。
reduce:
从第二个成员开始遍历,第一个成员将在第一次遍历的时候作为第一个参数
注意:
如果reduce方法传递了第二个参数,将从第一个成员遍历, 第二个参数就是初始化的值
reduceRight:
从倒数第二个成员开始遍历,倒数第一个成员在第一次遍历的时候作为第一个参数
注意:
如果reduceRight方法传递了第二个参数,从倒数第一成员遍历,第二个参数就是初始化的值
//reduce
var arr = [2, 4, 6, 8, 10];
// //求成员之和
// var result = arr.reduce(function () {
// console.log(arguments, this);
//默认从第二个开始遍历
// })
//求成员之和//需要从第一个数字开始遍历
var result = arr.reduce(function (res, item) {
console.log(arguments, this);
return res + item
}, null)//也可以传递0
//第一个成员将在第一次遍历的时候作为第一个参数
console.log(result);//30
2.10总结:学习方法
1.学会使用方法(记住传递的参数,返回值是什么)
2.如果参数是函数,必须了解参数以及返回值,对结果的影响
3.看this的指向
4.思考方法的实现过程
3. 函数拓展--函数绑定(bind)
3.1 bind方法
ES5对函数拓展了bind方法
作用:
为函数绑定作用域(当函数执行时,改变函数的作用域,并传递参数)
目前为止改变作用域的方法|关键字: bind, call, apply, with, eval
call与apply的区别:
他们都是改变函数this指向的方法,都是在调用该方法的时候,执行函数并改变this指向的,第一个参数都是改变的this指向的对象
call从第二个参数起,后面的参数都表示传递给函数的参数
apply第二个参数只有一个数组,每一个成员表示传递给函数的参数
3.2 bind与(call或apply)的区别
bind跟call类似
第一个参数表示改变的this指向的对象
从第二个参数开始,表示传递的参数
区别:
call | apply:
调用即执行
bind:
调用不执行,但是得到一个新的方法,可以执行
bind方法实现是通过apply实现的
3.3 bind的绑定与柯理化
bind通过两项技术实现的
(1) 函数绑定:
函数作为参数传递的同时,可以改变函数的this指向
作用:
改变this指向
(2)函数柯理化:
一个接收多个参数的函数,我们一个一个的传递参数,在函数执行的时候,传递剩余的参数并得到结果
作用:
增强了函数的适用性
1.跟函数的重载有点像
2.函数的重载是在函数内部实现的
3.函数柯理化是在函数外部实现的(没有修改函数内部结构,类似于装饰者模式,是对函数的包装)
/*** bind方法的实现
* 1.函数的绑定
* 函数作为参数传递的同时,在执行函数的时候才更改this指向
* 2.函数柯里化
*
* 1.函数的绑定
* @fn 执行的函数
* @context 上下文对象(需要传递的参数) **/
function bind(fn, context) {
//1.返回函数
return function () {
//1.1执行该函数,相当于执行fn
//1.2更改this指向,并传递参数
fn.apply(context, arguments) } }
//1.3测试
// var fn = bind(demo, obj)
// console.log(fn);//成功传递了函数且未执行
// fn(1, 2, 3);//执行了,指向obj且传递了Arguments都是以数组传递
// btn.onclick = bind(demo, obj)//正常传递事件且this指向正常
// btn.onclick = bind(demo, obj, 1, 2, 3)//不能传递参数,bind方法需要进行第二步改造
/*** 2.函数柯里化(增强了函数的适用性)
* 一个函数接收多个参数,我们一个一个的传递参数,
* 在函数执行的时候,传递剩余的参数并得到结果
* @fn 从第二个参数开始,表示传递的参数 * **/
//2.3只接收一个参数,返回该参数与20相加的结果,
//此时,不想重新再写个新的add方法,就使用 柯里化
function curry(fn) {
//2.31从第二个参数开始,表示传递的参数
var args = Array.prototype.slice.call(arguments, 1);
//2.32返回一个新函数
return function () {
//2.34直接合并不能传递好参数,需要将arguments转化成数组
var arr = Array.prototype.slice.call(arguments);//不传递参数相当于赋值所有的参数
//2.33获取当前参数(为了合并参数)
var all = [].concat(arr, args);//2.35改成arr后,两个位置都能传递参数了
// console.log(all);
//2.35指向原来的函数,传递剩余的参数(新函数的参数)
return fn.apply(null, all) } }
// //2.331;2.35测试
// var fn = curry(demo, 1, 2, 3)//位置1
// fn(4, 5, 6)//位置2
//2.1求两数和
function add(num1, num2) {
return num1 + num2 }
// console.log(add(45, 765));//810 √ //2.11测试
//2.2只接收一个参数,返回该参数与10相加的结果//2.4
var add10 = curry(add, 10);
var add20 = curry(add, 20); //2.3 +20的
var add100 = curry(add, 100); //+100
//测试
console.log(add(5, 6)); //11
console.log(add10(5));//15
console.log(add20(6));//26
console.log(add100(89));//189
//2.21在不改变原add传入的参数个数进行修改
// function add(num1, num2) {
// //参数重载,即根据参数的不同,做不同的处理
// //重载即重新载入,
// //但是,形参要写全。新add覆盖旧add,但可以传递两个,或者一个参数了
// if (num2 !== undefined) {
// return num1 + num2
// } else {
// return num1 + 10
// }
// }
// console.log(add(5, 6));//11
// console.log(add(5));//15
/** * 3.函数绑定的彻底实现
* 综合使用,1.函数绑定 和 2.函数柯里化实现 * **/
Function.prototype.qaqBind = function (context) {
//3.2获取剩余的参数
var args = Array.prototype.slice.call(arguments, 1);
//3.5 this实例就是方法//存储
var fn = this;
//3.1返回一个函数
return function () {
//3.3获取参数(实际经常要传递的参数)
var arr = Array.prototype.slice.call(arguments);
//3.4合并两处获取的参数//数组的拼接
var all = args.concat(arr);
//3.6执行函数,并传参
//此处不能直接用this是因为闭包,具体见闭包知识点
return fn.apply(context, all) } }
// var fn = demo.qaqBind(obj, 1, 2, 3); //测试
// fn(4, 5, 6)//Arguments(6) [1, 2, 3, 4, 5, 6 ]
btn.onclick = demo.qaqBind(obj, 2, 2, 2)
// this指向:{color: "red"} 后面参数的传递: Arguments(4) [2, 2, 2]
3. 4 原子继承(create)
ES5对对象拓展了一个静态方法,叫create, 实现对对象的继承
是对寄生式继承的一个拓展,可以看作是寄生工厂模式.
返回值是一个对象,就是继承了参数对象的新对象
继承下来的属性以及方法是可以修改的
3.5 日期--toJSON
toJSON将日期转化成json格式(标准化格式)
它返回UTC时区的ISO格式日期字符串(由后缀Z表示)。
是ES5新增的方法,增强对日期格式的可读性。
4. 严格模式
4.1历史
ES5新增了严格模块,可以使我们写的代码更加的安全可靠
js运行环境就有了两种模式:严格模式,正常模式
js诞生之初只是为了实现一些简单的交互,随着技术的发展, js需要做的事情越来越多,js其自身的一些糟粕部分就暴露出来了,这些问题,浏览器通常检测不出来,所以常常是隐藏的bug,为了屏蔽这些问题,ES5提出了严格模式,常见的问题诸如:
1.定义变量省略var污染全局环境
2.执行eval方法污染全局环境,
3.使用arguments.callee无法编译优化
总之,两类大问题:1.语法上的问题; 2. 无法编译优化(性能优化)的问题
4.2进入严格模式(“use strict ”)
进入严格模式非常简单,直接添加一行”use strict"字符串即可
高级浏览器识别它,会自动进入严格模式
低级浏览器不识别,只是当作一行简单的字符串处理
所以对于高级浏览器以及低级浏览器都没有副作用,所以工作中,建议使用严格模式
全局与局部:
1.如果在js的第一行加入"use strict"。此时,代码将处于“全局严格模式”
2.如果在某个函数的第一行加入"use strict",当函数执行的时候,该函数将处于" 局部严格模式’’
//Global scope use strict
'use strict'//1.4 just add this row
//1.1 Omit var when defining variables
function demo() {
color = 'red'; }//1.2 pollution global scope
demo();
console.log(color);
//1.3 red is in the global scope//1.5
// num = 100;//1.5
//1.5 Now browser will push Errow :not a funcition
//Part 'use strict'
function demo() {
'use strict'; color = 'red'; }
demo();//run function , fn inner will get in strict mode
//outer also is a normol mode
4.3严格模式规范
(1) 全局严格模式
定义变量不能省略var,省略了var就抛出错误;
注意:全局严格模式只能在当前标签执行
(2)局部严格模式
在js中执行函数的时候,我们也可以进入严格模式,就是在函数开头添加”use strict" 字符串,此时函数内部是严格模式的,函数外部就是正常模式,只有当函数执行的时候,才能进入严格模式,函数外面仍然是正常模式,直到函数执行完毕,严格模式被解除。
(3)全局函数作用域
正常模式下,全局函数作用域是window,进入严格模式,全局函数作用域是undefined。
以前正常模式下,在函数内部通过this修改数据会污染全局作用域,严格模式下会抛出错误,就不会污染全局作用域
//Influence of strict mode on scope
//1.5 strict mode
'use strict'//44th row will push Error
//1.1 settig fn
function Demo() {
this.color = 'red';
console.log(this);
}
// new Demo();//正常情况下 this指向 Demo
Demo()//1.3 instantiating(实例化) forget add 'new'
console.log(window.color);//1.2 undefined //1.4 red
(4)函数参数
正常模式下,函数可以定义同名参数,但是会产生覆盖问题,前面的参数被覆盖,严格模式下不允许定义同名的参数。
//进入严格模式Enter strict mode
'use strict'
function demo(color, color) {//函数参数function arguments
console.log(color); }
demo('red', 'green');//不使用严格输出green,后面的覆盖前面的
//使用严格模式,报错
(5)对象属性
严格模式下,在通过对象字面量形式定义对象的时候,不允许定义同名的属性,定义同名的属性,前面的会被覆盖,目前还没有浏览器提示错误。
'use strict';//该模式的这种情况不会报错
//定义对象Define object
var obj = {
//定义两个同名属性,后面覆盖前面,前面的定义无意义
//Define two properties with the same name
color: 'red',
color: 'pink' }
// obj.color = 'green';
console.log(obj);//{color: "green"}//'pink'
(6) delete关键字
只能用来删除对象的属性的,正常模式下,可以删除变量,函数等,但是没有删除成功。严格模式下,不允许去删除变量、函数等,只能删除对象的属性,否则会抛出错误。
// (6) delete关键字 'use strict'; var color = 'red'; function demo() { console.log('demo'); } var obj = { num: 100, msg: 'hello' } //删除数据 //下面两个是无效的使用,严格模式会报错 delete color; delete demo; //普通情况,只有对象的属性可以删除成功 delete obj.num; console.log(color);//red demo();//demo console.log(obj);//{msg: "hello"}//num成功删除
(7)关键字、保留字、特殊变量
严格模式下不允许用关键字,保留字,特殊性变量来定义变量
关键字:
具有一定功能的单词: var,function, for,while等
保留字:
当前版本没有使用,将来某个版本将被使用的变量: class, public等等
特殊变量:
在特定环境下具有一定功能的变量: arguments, eval等
在严格模式下,用这些单词定义变量会抛出错误
'use strict';//严格模式下,一下都不能使用
//(7)关键字、保留字、特殊变量
// var function=100;//关键字:正常模式报错
var public = 200;//保留字:正常模式不报错
var arguments = 300;//特殊变量:正常模式不报错
console.log(public, arguments);//200 300
(8) 8进制
js中以0开头的数字:
普通模式中,如果后面的数字出现大于等于8的,就是10进制,如果后面的数字都小于8,就是8进制。所以容易出现混乱,所以严格模式下不允许使用8进制的数(数字不能以0开头)
(9)特殊字符
由于字符集的限制,有些字符,不能书写出来,可以通过特殊字符表达。
例如:\012表示一个换行,有时候为了避免字符冲突,我们也要转义,例如在单引号定义的字符串中,使用单引号。这样转义后,有的仍然是其自身,有的变成其他字符了,有歧义,因此严格模式不允许使用特殊字符。
严格模式下可以使用转义字符,但是不能使用特殊字符
'use strict'
// //define string 特殊字符 \ + 字符码
// var str1 = 'qaq\012hello';//严格模式直接报错
// var str2 = 'qaq\1hello';//严格模式直接报错
// console.log(str1);//普通模式:换行成功
// console.log(str2);//普通模式:qaqhello
//可以使用转义字符
var str1 = 'hello\'qaq';
var str2 = 'hello\nqaq';
console.log(str1);//hello'qaq严格模式下,可以执行
console.log(str2);//换行成功
(10) eval
eval可以将字符串作为语句去执行,但是会污染全局作用域。
严格模式下,可以避免对全局作用域的污染。
ES5对eval的处理是识别该特殊变量,并没有改变其功能,因此仍然想使用原有的功能,我们可以将eval赋值给一个变量,然后通过该变量去执行
'use strict'
//eval //普通模式:全局中执行eval语句,污染全局
eval('var a = 10;console.log(a)')//普通模式:定义在全局//严格模式:10
// console.log(a);//10//严格模式下:未定义(只能在eval内查看)
//严格模式中,只识别eval关键字,没有改变其功能
var newEval = eval;
newEval('var b=20;')
console.log(b);//严格模式:20
// function demo() {//普通模式的:函数中执行
// eval('var b = 20;') console.log(b); }//20
// demo();
(11) arguments.callee
在函数内部访问该函数:
解决函数的执行时与函数名称耦合的问题(常用在递归中)。在浏览器渲染js的时候,并不是直接执行js语句,而是将js编译,执行编译的代码。
但是由于arguments.callee无法被编译引擎编译优化,所以严格模式下不允许使用。js是动态语言,执行时候的是作用域,因此在编译的时候js没有执行,因此arguments.callee到底指向哪个函数名称,编译引擎不知道,所以无法优化
'use strict'//严格模式arguments.callee不能使用
//以下都是普通模式2.为了解决耦合,js提供了arguments.callee
function add(num) {
if (num <= 1) {
return num
} else {
// return num + add(num - 1)
return num + arguments.callee(num - 1) } }
console.log(add(5));//15
console.log(add(15));//120
var qaq = add; //换一个函数名称
//删除add变量名称
add = null;//1.报错:add方法与函数add内部的add耦合了
console.log(qaq(68));//2346
(12) with
可以更改代码执行时候的this指向,严格模式下不能使用with,因为with无法让编译引擎编译优化。js 在编译的时候,无法执行with语句,也就是说,在with语句内部出现的变量,我们不知道是全局的还是更改的对象中的,因此有歧义,所以严格模式不允许使用。
'use strict'
console.log(Math.max(12, 234, 65, 4));//234//使用数学对象提供的方法
console.log(Math.PI);//3.141592653589793
// with :可以更改代码执行时候的this指向
with (Math) {
console.log(PI);//3.141592653589793
console.log(abs(-2));//2
console.log(random()); }
var a = 10; var b = 20;
var obj = { b: 30,c: 40}
console.log(a + b);//30
with (obj) {
//在obj对象下执行,优先使用obj作用域内的属性
//在编译的时候,函数未执行,电脑无法识别a的指向,因此严格模式会报错
console.log(a + b); }//40
5. 特性
5.1含义
对象是什么,我们用属性来说明
属性是什么,我们用特性来说明
特性的作用:
就是用来说明属性。
5.2定义特性(Object.defineProperty)
Object.defineProperty(obj, prop, property)
obj :表示对象
prop:表示对象的属性
property:表示属性的特性,是个对象
5.2.1四个属性
特性对象有四个属性
value表示属性的值
writable表示属性是否可以修改
true 可以修改
false 不能修改
enumerable表示属性是否可以被枚举。例如,是否可以通过for in遍历
true 可以遍历
false 不可遍历
configurable表示属性是否可以再次被配置(是否可以再次更改这些特性)
true 可以配置
false 不能配置
除了value,其余都是布尔值
5.2.2特性方法
特性对象有两个方法
注意:
1.这两个方法不能与value和writable兼容(不能一起定义)
2.但是,可以同enumerable与configurable一起使用
get获取属性的值
1.没有参数
2.this指向这个对象
3.返回值:这个属性的值
注意:绝对不能在该方法内部获取该属性,否则递归死循环
4.工作中,通常获取的是这个值的备用值
set修改属性的值
1.参数:修改的新的值
2. this指向这个对象
3.返回值:无意义
注意:绝对不能在该方法内部修改该属性,否则递归死循环
4.工作中,通常修改的是这个值的备用值
var obj = {num: 100};
//1.add propert
Object.defineProperty(obj, 'color', {
value: 'red',
writable: true,//4.是否能被修改
enumerable: true,//7.是否可以被遍历
configurable: true//9.是否可以再次被配置
// configurable: false//9.是否可以再次被配置
})
//8.不可以再次被配置
Object.defineProperty(obj, 'color', {
writable: false,
enumerable: false})
//9.特性方法
Object.defineProperty(obj, 'msg', {
//9.1取值器(获取属性)
get: function () {
// return 'hello'//11.2注释此行
console.log(this, arguments);//11.1输入此行
// //11.4 绝对不能获取当前属性
// console.log(111);
// return this.msg//死循环
//11.5返回备份数据
return this._msg;//可以在控制台点击msg(...)手动慢速死循环= =
},
//9.2get和set不能与value和writable一起定义
// value: 'abc'
//10.1复制器方法(修改属性)
set: function (value) {
console.log(this, arguments);//10.3
// {num: 100, color: "red"}
// Arguments ["qaq", callee: ƒ, Symbol(Symbol.iterator): ƒ]
//10.4 绝对不能修改当前属性
// this.msg = value;//死循环
this._msg = value;}, //10.5修改备份数据
enumerable: true, //12.枚举
configurable:false}) //13.不能再次被配置
obj.msg = 'qaq'; //10.2修改属性
obj.color = 'green'; //3.modify property 默认false修改不了
for (var key in obj) {//6.遍历
console.log(key, obj[key]);
//6.1num 100;没有遍历到green;enumerable默认false
}
console.log(obj);
//2.{num: 100, color: "red"}//5.{num: 100, color: "green"}
//10.6{num: 100, _msg: "qaq", color: "red"}
console.log(obj.msg);//11.3undefined//11.6qaq
5.2.3定义多个属性特性
Object.defineProperties(obj, propsProperty)
obj 表示原对象 propsProperty 表示属性特性对象
key 表示属性名称 value 就是特性对象
//定义对象
var obj = {num: 10}
//定义多个属性的特性
Object.defineProperties(obj, {
num: {writable: false},
color: {value: 'red',
writable: true},
msg: {set: function (value) {this._msg = value;},
get: function () {return this._msg},
enumerable: true}})
console.log(obj);
// msg: (...) num: 10 color: "red" get msg: ƒ ()
5.3. 自身属性
5.3.1判断自身属性(hasOwnProperty)
for in循环可以遍历对象的自身属性以及原型属性。
有时候需要遍历自身属性,不遍历原型方法我们可以
使用hasOwnProperty方法
obj.hasOwnProperty(prop)
对象调用
参数:这个属性
返回值:
true:表示自身属性
false:表示原型属性
5.3.2获取属性名称(0bject.getOwnPropertyNames)
有时我们只想获取所有自身属性名称可以使用
参数:这个对象
返回值:获取的所有属性,是一个数组
即使属性设置了特性,也可以获取
不能获取原型上的属性
//即使,自身的属性设置了特性,也可以获取到
Object.defineProperties(book, {
writer: {},color: {},
time: {
set: function () { },
get: function () { }}})
//只想打印自身的属性,获取自身属性
var keys = Object.getOwnPropertyNames(book);
console.log(keys);// ["title", "price"]//["title", "price", "writer", "color", "time"]
5.3.3查看属性特性(Object.getOwnPropertyDescriptor())
ES5新增一个方法, Object.getOwnPropertyDescriptor() 可以查看属性的特性
Object.getOwnPropertyDescriptor(obj, prop)
obj表示这个对象 prop表示这个属性
返回值:是一个特性对象
5.4特性总结
1对象原有的属性,特性默认值都是true (writable, enumerable, configurable)
2特性方法为对象新增的属性,特性默认值都是false
3特性中的set, get与value, writable不兼容
4属性的特性默认优先设置value和writable
6.原型拓展
6.1判断原型(isPrototypeOf)
作用:
ES5新增了一个isPrototypeOf方法可以判断对象的原型对象,
注意:
这个方法查找整个原型链
用法:
类的原型.isPrototypeOf(对象)
类的原型是否被对象继承了(对象的原型链 上是否可以找到这个类)
让原型属性不可枚举,使用方式:
Object.defineProperty(类的原型对象, property, {
enumerable: false
//不可枚举
})
6.2操作原型
获取原型: Object.getPrototypeOf
以前获取对象的原型用__ proto__ ,但是__ proto__ 属性以__ 开头,属于私有的属性,是不希望我们使用的,因此ES5新增Object.getPrototypeOf方法,用来获取对象的原型的,与__proto__ 属性是等价的
//获取arr的原型 //__:双下划线开头的属性不建议使用
console.log(arr.__proto__);//[constructor: ƒ, concat: ƒ,…]
console.log(Object.getPrototypeOf(arr));//[constructor: ƒ, concat: ƒ,…]
修改原型: Object.setPrototypeOf
该方法用于设置某个对象的原(继承原型)
使用方式: Object.setPrototypeOf(obj, prototype)
obj:要设置新的原型的对象
prototype:要设置的新的原型(可以是null可以是一个对象)
7. 对象操作
对象有四个操作:
增(拓展,增加) ,删(删除),改(修改),查(查看)
7.1对象禁拓(Object.preventExtensions)
1.对象的禁拓(禁止拓展)就是说:
该对象不能拓展属性(新增属性)
但是可以删除属性,修改属性和查看属性
2.Object.preventExtensions方法
用于取消对象的可拓展性
参数:就是这个对象
禁拓是不可逆的,一旦禁拓就无法解除
查看是否禁拓用: Object.isExtensible
如果返回的是false,表示被禁拓了
true表示没有被禁拓,可以新增属性
//对象的操作
var obj = {
color: 'red',
num: 1023
}
console.log(Object.isExtensible(obj));//true//在禁拓前都可拓展
//禁拓
Object.preventExtensions(obj);//禁拓后:{color: "green"}
console.log(Object.isExtensible(obj));//false//在禁拓后都不可拓展
//拓展属性:增
obj.msg = 'hello';
//删除属性:删
delete obj.num;
//修改属性:改
obj.color = 'green';
//查看属性:查
console.log(obj);//禁拓前:{color: "green", msg: "hello"}
7.2对象封闭(Object.seal)
对象的封闭就是说
不能对对象添加属性,删除属性
但是可以修改属性和查看属性
Object.seal方法,来封闭一个对象
参数:就是这个对象
封闭是不可逆的,一旦封闭就无法解封
查看是否封闭用: Object.isSealed
如果返回的是true表示被封闭了,反之则没有被封闭
console.log(Object.isSealed(obj))//false
//对象封闭
Object.seal(obj)//后:{color: "green", num: 1023}
console.log(Object.isSealed(obj))//true
7.3对象冻结(Object.freeze)
对象的冻结就是说
不能对对象添加属性,删除属性,修改数据
只能对对象查看属性
Object.freeze方法,来冻结一个对象
参数:就是这个对象
冻结是不可逆的,一旦冻结就无法解冻
查看是否冻结用: Object.isFrozen
如果返回true表示被冻结了,反之则没有被冻结
console.log(Object.isFrozen(obj))//false
//对象冻结
Object.freeze(obj)//后:{color: "red", num: 1023}
console.log(Object.isFrozen(obj))//true