ES5-01

目录

1. JSON语法... 3

1.1JSON—parse/stringify. 3

2.数组... 3

2.1判断数组... 3

2.2获取数组索引值... 4

2.3 forEach(返回值undefined)... 4

2.4 map(返回值有意义)... 5

2.5 fill(填充数组的方法)... 6

2.6  filter(由符合条件的成员组成新数组)... 6

2.7 some(断言方法)... 7

2.8 every(断言方法)... 7

2.9 reduce与reduceRight(累加方法)... 8

2.10总结:学习方法... 9

3. 函数拓展--函数绑定(bind)... 9

3.1 bind方法... 9

3.2 bind与(call或apply)的区别... 10

3.3 bind的绑定与柯理化... 10

3. 4 原子继承(create)... 12

3.5 日期--toJSON.. 13

4. 严格模式... 13

4.1历史... 13

4.2进入严格模式(“use strict ”) 13

4.3严格模式规范... 14

(1) 全局严格模式... 14

(2)局部严格模式... 14

(3)全局函数作用域... 14

(4)函数参数... 15

(5)对象属性... 15

(6) delete关键字... 15

(7)关键字、保留字、特殊变量... 16

(8) 8进制... 16

(10) eval 17

(11) arguments.callee. 17

(12) with. 18

5. 特性... 18

5.1含义... 18

5.2定义特性(Object.defineProperty)... 18

5.2.1四个属性... 19

5.2.2特性方法... 19

5.2.3定义多个属性特性... 21

5.3. 自身属性... 21

5.3.1判断自身属性(hasOwnProperty)... 21

5.3.2获取属性名称(0bject.getOwnPropertyNames) 22

5.3.3查看属性特性(Object.getOwnPropertyDescriptor())... 22

5.4特性总结... 22

6.原型拓展... 23

6.1判断原型(isPrototypeOf)... 23

6.2操作原型... 23

7. 对象操作... 24

7.1对象禁拓(Object.preventExtensions)... 24

7.2对象封闭(Object.seal)... 25

7.3对象冻结(Object.freeze)... 25

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:一个都不满足条件

sometrue敏感,遇到一个满足条件的成员,就停止执行。 

   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:至少有一个成员满足条件

everyfalse敏感,遇到一个不满足条件的成员,停止遍历

      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

callapply的区别:

他们都是改变函数this指向的方法,都是在调用该方法的时候,执行函数并改变this指向的,第一个参数都是改变的this指向的对象

call从第二个参数起,后面的参数都表示传递给函数的参数

apply第二个参数只有一个数组,每一个成员表示传递给函数的参数

3.2 bind与(call或apply)的区别

bindcall类似

第一个参数表示改变的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.这两个方法不能与valuewritable兼容(不能一起定义)

2.但是,可以同enumerableconfigurable一起使用

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)

有时我们只想获取所有自身属性名称可以使用

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, getvalue, writable不兼容

4属性的特性默认优先设置valuewritable

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值