一、对象方法
1.1、Object.keys()
1.1.1、概述
1 2 3 4 5 6
| # 语法 Object.keys(obj) # 含义 用于获取对象自身所有的属性 1. 效果类似 for…in 2. 返回一个由属性名组成的数组
|
1.1.2、案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <body> <script> var person = { id: 1, uname: 'HelloWorld', age: 23 };
var keys = Object.keys(person); console.log(keys);
for (var i = 0; i < keys.length; i++) { var key = keys[i]; console.log(person[key]); } </script> </body>
|
1.2、Object.defineProperty()
1.2.1、概述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| # 语法 Object.defineProperty(obj, prop, descriptor) # 含义 定义对象中新属性或修改原有的属性。 1、参数一obj: 必需。目标对象 2、参数二prop:必需。 需定义或修改的属性的名字 3、参数三descriptor:必需。目标属性所拥有的特性,该参数是一个对象的形式表示。 value: 设置属性的值 默认为undefined writable: 值是否可以重写。true | false 默认为false enumerable: 目标属性是否可以被枚举。true | false 默认为 false configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false 默认为false
|
1.2.2、案例1
在原有对象身上添加新属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <body> <script> var person = { id: 1, uname: 'HelloWorld', age: 23 };
Object.defineProperty(person, 'address', { value: '浙江省' });
console.log(person); </script> </body>
|
1.2.3、案例2
修改原对象身上的uname
属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <body> <script> var person = { id: 1, uname: 'HelloWorld', age: 23 };
Object.defineProperty(person, 'uname', { value: 'JavaScript' });
console.log(person); </script> </body>
|
1.2.4、案例3
设置属性不能修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <body> <script> var person = { id: 1, uname: 'HelloWorld', age: 23 };
Object.defineProperty(person, 'uname', { writable: false });
person.uname = 'HTML';
console.log(person); </script> </body>
|
1.2.5、案例4
enumerable
: 目标属性是否可以被枚举。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <body> <script> var person = { id: 1, uname: 'HelloWorld', age: 23 };
Object.defineProperty(person, 'address', { value: '杭州市', enumerable: false });
console.log(Object.keys(person)); </script> </body>
|
1.2.6、案例5
configurable
如果为false 则不允许删除这个属性 默认为false。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <body> <script> var person = { id: 1, uname: 'HelloWorld', age: 23 };
Object.defineProperty(person, 'uname', { configurable: false });
delete person.uname;
console.log(Object.keys(person)); </script> </body>
|
二、函数的定义和调用
2.1、函数的定义方式
2.1.1、自定义函数/命名函数
1 2 3 4 5 6 7 8 9
| <body> <script> function fn() { console.log('--fn--'); } </script> </body>
|
2.1.2、函数表达式/匿名函数
1 2 3 4 5 6 7 8 9
| <body> <script> var fn = function() { console.log('--fn--'); } </script> </body>
|
2.1.3、利用 new Function
1 2 3
| # 语法 new Function('参数1','参数2', '函数体'); 1. Function 里面参数都必须是字符串格式
|
1 2 3 4 5 6 7 8
| <body> <script> var fn = new Function("console.info('HelloWorld')"); fn(); </script> </body>
|
1 2 3 4 5 6 7 8
| <body> <script> var fn = new Function("a", "b", "console.info(a + b)"); fn(10, 20); </script> </body>
|
1 2 3 4 5 6 7 8
| <body> <script> var fn = new Function("a", "b", "console.info(a + b)"); console.log(fn instanceof Object); </script> </body>
|
1 2 3
| # 说明 1. 所有函数都是 Function 的实例(对象) 2. 函数也属于对象
|
2.2、函数的调用方式
2.2.1、普通函数
1 2 3 4 5 6 7 8 9 10
| <body> <script> function fn() { console.log('--fn--'); } fn(); </script> </body>
|
1 2 3 4 5 6 7 8 9 10
| <body> <script> function fn() { console.log('--fn--'); } fn.call(); </script> </body>
|
2.2.2、对象的方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| <body> <script> var person = { run: function() { console.log('--run--'); } }
person.run(); </script> </body>
|
2.2.3、构造函数
1 2 3 4 5 6 7 8 9 10 11
| <body> <script> function Person() { console.log('---构造函数---'); }
new Person(); </script> </body>
|
2.2.4、绑定事件函数
1 2 3 4 5 6 7 8 9 10 11 12
| <body> <button>注册</button> <script> var btnObj = document.querySelector('button');
btnObj.onclick = function() { console.log('--注册--'); } </script> </body>
|
2.2.5、定时器函数
1 2 3 4 5 6 7 8 9
| <body> <script> setTimeout(function() { console.log('---定时器函数---'); }, 2000); </script> </body>
|
2.2.6、立即执行函数
1 2 3 4 5 6 7 8 9
| <body> <script> (function(num) { console.log('--' + num); })(30); </script> </body>
|
2.2.7、总结
1 2 3 4 5 6 7
| # 函数的调用方式 1. 普通函数 2. 对象的方法 3. 构造函数 4. 绑定事件函数 5. 定时器函数 6. 立即执行函数
|
三、this关键字
3.1、函数内 this 的指向
3.1.1、说明
这些 this 的指向,是当我们调用函数的时候确定的。 调用方式的不同决定了this 的指向不同。通常来说,一般指向我们的调用者。
3.1.2、图示
3.1.3、普通函数调用
1 2 3 4 5 6 7 8 9 10
| <body> <script> function fn() { console.log('普通函数的this-->', this); } fn(); </script> </body>
|
3.1.4、对象方法调用
1 2 3 4 5 6 7 8 9 10 11 12
| <body> <script> var person = { run: function() { console.log('对象方法的this', this); } }; person.run(); </script> </body>
|
1
| # 对象的方法 this指向的是对象 person
|
3.1.5、构造函数调用
1 2 3 4 5 6 7 8 9 10
| <body> <script> function Star() { console.log('构造方法的this-->', this); } var zhangsan = new Star(); </script> </body>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <body> <script> function Star() { console.log('构造函数的this', this); } Star.prototype.run = function() { console.log('方法', this); } var zhangsan = new Star(); zhangsan.run(); </script> </body>
|
1
| # 构造函数 this 指向 zhangsan 这个实例对象 原型对象里面的this 指向的也是 zhangsan 这个实例对象。
|
3.1.6、绑定事件函数调用
1 2 3 4 5 6 7 8 9 10 11
| <body> <button>注册</button> <script> var btnObj = document.querySelector('button'); btnObj.onclick = function() { console.log('注册事件处理函数的this', this); } </script> </body>
|
1
| # 绑定事件函数 this 指向的是函数的调用者 button 这个按钮对象
|
3.1.7、定时器函数调用
1 2 3 4 5 6 7 8 9
| <body> <script> setTimeout(function() { console.log('定时器的this', this); }, 3000); </script> </body>
|
1
| # 定时器函数 this 指向的也是window
|
3.1.8、立即执行函数调用
1 2 3 4 5 6 7 8 9
| <body> <script> (function() { console.log('立即函数的this', this); })(); </script> </body>
|
3.2、改变函数内部 this 指向
3.2.1、说明
JavaScript 为我们专门提供了一些函数方法来帮我们更优雅的处理函数内部 this 的指向问题,常用的有 bind()、call()、apply() 三种方法。
3.2.2、call方法
3.2.2.1、说明
1 2 3 4 5 6 7 8 9 10 11
| # 语法 fun.call(thisArg, arg1, arg2, ...) # 说明 1、thisArg:在 fun 函数运行时指定的 this 值 2、arg1,arg2:传递的其他参数 3、返回值就是函数的返回值,因为它就是调用函数 4、因此当我们想改变 this 指向,同时想调用这个函数的时候,可以使用 call,比如继承。 # 作用 1、可以调用函数 2、实现继承
|
3.2.2.2、案例1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <body> <script>
var person = { uname: 'HelloWorld' };
function fn(a, b) { console.log(this); console.log(a + b); }
fn.call(person, 10, 20); </script> </body>
|
3.2.2.3、案例2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <body> <script>
function Father(uname, age) { this.name = name; this.age = age; } function Child(uname, age, address) { Father.call(this, uname, age); this.address = address; }
var zhangsan = new Child('张三', 20, '河南省'); console.log(zhangsan.uname); console.log(zhangsan.age); console.log(zhangsan.address); </script> </body>
|
3.2.3、apply 方法
3.2.3.1、说明
1 2 3 4 5 6 7
| # 语法 fun.apply(thisArg, [argsArray]) # 说明 1. thisArg:在fun函数运行时指定的 this 值 2. argsArray:传递的值,必须包含在【数组】里面 3. 返回值就是函数的返回值,因为它就是调用函数 4. apply 主要跟数组有关系,比如使用 Math.max() 求数组的最大值
|
3.2.3.2、案例1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <body> <script>
var person = { uname: 'HelloWorld' }
function fn(a, b) { console.log(this); console.log('a + b = ' + (a + b)); }
fn.apply(person, [10, 20]); </script> </body>
|
3.2.3.3、案例2
apply
的主要应用 比如说我们可以利用 apply 借助于数学内置对象求数组最大值。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <body> <script>
var arrs = [10, 21, 18, 34, 23];
var result = Math.max.apply(Math, arrs); console.log(result); </script> </body>
|
3.2.4、bind 方法
3.2.4.1、说明
1 2 3 4 5 6 7 8 9
| # 语法 fun.bind(thisArg, arg1, arg2, ...) 方法不会调用,但是也会改变函数this的指向。 # 说明 1. thisArg:在 fun 函数运行时指定的 this 值 2. arg1,arg2:传递的其他参数 3. 返回由指定的 this 值和初始化参数改造的原函数拷贝,也就是说返回的是一个函数,一个原函数的一个拷贝。 4. 因此当我们只是想改变 this 指向,并且不想调用这个函数的时候,可以使用 bind
|
3.2.4.2、案例1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <body> <script>
var person = { uname: 'HelloWorld' };
function fn(a, b) { console.log(this); console.log("a + b = " + (a + b)); }
var f = fn.bind(person, 10, 30);
f(); </script> </body>
|
3.2.4.3、案例2
如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind。
我们有一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮。
错误的代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <body> <button>注册</button> <script>
var btnObj = document.querySelector('button');
btnObj.onclick = function() { this.disabled = true; setTimeout(function() { this.disabled = false; }, 3000); } </script> </body>
|
正确的代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <body> <button>注册</button> <script>
var btnObj = document.querySelector('button');
btnObj.onclick = function() { this.disabled = true; var that = this; setTimeout(function() { that.disabled = false; }, 3000); } </script> </body>
|
3.2.4.4、案例3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <body> <button>注册</button> <script>
var btnObj = document.querySelector('button');
btnObj.onclick = function() { this.disabled = true; setTimeout(function() { this.disabled = false; }.bind(this), 3000); } </script> </body>
|
3.2.4.5、案例4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <body> <button>注册</button> <button>注册</button> <button>注册</button> <script>
var btnObjs = document.querySelectorAll("button");
for (var i = 0; i < btnObjs.length; i++) { btnObjs[i].onclick = function() { this.disabled = true; setTimeout(function() { this.disabled = false; }.bind(this), 3000); } } </script> </body>
|
3.3、call 、apply、bind 总结
1 2 3 4 5 6 7 8 9 10
| # 相同点 都可以改变函数内部的this指向。 # 区别点 1. call 和 apply 会调用函数, 并且改变函数内部this指向. 2. call 和 apply 传递的参数不一样, call 传递参数 arg1, arg2..形式 apply 必须数组形式[arg] 3. bind 不会调用函数, 可以改变函数内部this指向. # 主要应用场景 1. call 经常做继承. 2. apply 经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值 3. bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.
|
四、严格模式
4.1、什么是严格模式
JavaScript 除了提供正常模式外,还提供了严格模式(strict mode)。ES5 的严格模式是采用具有限制性 JavaScript 变体的一种方式,即在严格的条件下运行 JS 代码。
严格模式在 IE10 以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。
严格模式对正常的 JavaScript 语义做了一些更改:
- 消除了 Javascript 语法的一些不合理、不严谨之处,减少了一些怪异行为。
- 消除代码运行的一些不安全之处,保证代码运行的安全。
- 提高编译器效率,增加运行速度。
- 禁用了在 ECMAScript 的未来版本中可能会定义的一些语法,为未来新版本的 Javascript 做好铺垫。比如一些保留字如:class, enum, export, extends, import, super 不能做变量名。
4.2、开启严格模式
4.2.1、说明
严格模式可以应用到整个脚本或个别函数中。因此在使用时,我们可以将严格模式分为脚本开启严格模式和为函数开启严格模式两种情况。
4.2.2、为脚本开启严格模式
为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句“use strict”;(或‘use strict’;)。
1 2 3 4 5 6 7 8
| <body> <script> 'use strict'; console.log('这是严格模式...'); </script> </body>
|
有的 script 基本是严格模式,有的 script 脚本是正常模式,这样不利于文件合并,所以可以将整个脚本文件放在一个立即执行的匿名函数之中。这样独立创建一个作用域而不影响其他 script 脚本文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <body> <script> (function() { 'use strict'; var num = 20; console.log(num);
function run() {
} })(); </script> </body>
|
4.2.3、为函数开启严格模式
要给某个函数开启严格模式,需要把“use strict”; (或 ‘use strict’; ) 声明放在函数体所有语句之前。
将 “use strict” 放在函数体的第一行,则整个函数以 “严格模式” 运行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <body> <script> function run() { 'use strict'; console.log('该函数在严格模式下运行'); } function sing(){ } </script> </body>
|
4.3、严格模式中的变化
4.3.1、说明
严格模式对 Javascript 的语法和行为,都做了一些改变。
4.3.2、变量规定
- 在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,变量都必须先用var 命令声明,然后再使用。
- 严禁删除已经声明变量。例如,delete x; 语法是错误的。
1 2 3 4 5 6 7 8 9
| <body> <script> 'use strict'; num = 20; console.log(num); </script> </body>
|
1 2 3 4 5 6 7 8 9 10
| <body> <script> 'use strict'; var num = 20; delete num; </script> </body>
|
4.3.3、严格模式下 this 指向问题
- 以前在全局作用域函数中的 this 指向 window 对象。
- ==严格模式下全局作用域中函数中的 this 是 undefined。==
- 以前构造函数时不加 new也可以 调用,当普通函数,this 指向全局对象。但是在严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错
- new 实例化的构造函数指向创建的对象实例。
- 定时器 this 还是指向 window 。
- 事件、对象还是指向调用者。
1 2 3 4 5 6 7 8 9 10 11 12
| <body> <script> 'use strict';
function fn() { console.log(this); } fn(); </script> </body>
|
1 2 3 4 5 6 7 8 9 10 11 12
| <body> <script> 'use strict';
function Star() { this.uname = '张三'; } Star(); </script> </body>
|
1 2 3 4 5 6 7 8 9 10 11
| <body> <script> 'use strict';
setTimeout(function() { console.log(this); }, 3000); </script> </body>
|
4.3.4、函数变化
- 函数不能有重名的参数。
- 函数必须声明在顶层。新版本的 JavaScript 会引入“块级作用域”( ES6 中已引入)。为了与新版本接轨,不允许在非函数的代码块内声明函数。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <body> <script> 'use strict';
function sum(a, a) { console.log(a + a); }
sum(10, 20); </script> </body>
|
1 2 3 4 5 6 7 8 9 10 11 12
| <body> <script> 'use strict';
if (true) { function run() { console.log('helloworld'); } } run(); </script> </body>
|