函数调用方式
- 普通构造函数调用:内部的this指向全局对象window;
- 构造函数调用:内部的this指向新创建的对象;
- 对象的方法调用 :内部的this指向调用的对象本身;
- 通过call或者是apply 的方式调用(函数上下文),this指向的是当前上下文对象。
var obj = {
name : 'zs',
showName : function () {
console.log(this.name);
}
}
obj.showName();//this -->obj(构造函数调用)
var showName = obj.showName;
showName();//this -->window(普通函数调用)
var div = document.getElementById('demo');//-->this-->document
//问题:document.getElementById这个方法有this,默认指向document。
var getDiv =document.getElementById;
getDiv('demo');//this -->window
// 如何保证document.getElementById这个方法内部的this始终绑定document
var getDiv = (function (func) {
return function () {
return func.apply(document,arguments);
}
})(document.getElementById)
console.log(getDiv('demo'))
//首先执行立即执行函数,return一个函数function () { return func.apply(document,arguments);},然后传入参数"demo1",即document.getElementById。apply(document,demo)
图书管理操作
面向对象编程:
- 提供构造函数,在构造函数内部设置实力属性;
- 把常用的操作提取成对象的实例方法,卸载原型对象身上;
- 提供init方法,用于初始化数据;
- 注意:如果切断了原型对象,需要修正内部的构造器属性指向。
//面向过程
//1.提供一个构造函数
function BookManger(books) {
this.init(books);
}
//2.设置原型
BookManger.prototype = {
//修正构造器属性
constructor :BookManger,
//提供一个初始化的方法
init : function (books) {
this.dataList = books || [];
},
getBookByName :function (name) {
for (var i = 0; i < this.dataList.length; i++) {
var obj = this.dataList[i];
//判断
if(obj.name == name){
return obj
}
}
return null;
},
addBook :function (book) {
this.dataList.push(book);
},
updateBookByName : function (name,author) {
//1.查询(在原型方法中调用原型方法要写this)
var obj = this.getBookByName(name);
obj.author = author;
},
deleteBook:function (name) {
//1.查询
var obj = this.getBookByName(name)
//2.删除
var index = this.dataList.indexOf(obj);
if(index == -1){
throw '没有这本书!!!';
}
this.dataList.splice(index,1);
}
}
}
严格模式
关键字:"use strict";
关键字使用说明:
- 区分大小写,必须全部都是小写的;
- 注意空格。整个字符串总共10个字符;
- 必须使用单引号或者是双引号括住字符串;
- 必须写在作用域的最顶部,注意其位置;
- 可以加分号,也可以不加,但是必须为一个字符串。
严格模式注意点:- 所有的变量必须使用var 关键字声明(undefined);
- 不能使用delete关键字删除全局变量 ,以前默认删除失败,严格模式下直接报错
在非严格模式下,删除失败(静默失败),失败了不吭声,严格模式下直接报错
- 在对象中不允许有同名的属性(报错);
在非严格模式下,会使用后面的属性赋值作为最终值,在严格模式下则直接报错
- 函数的参数必须唯一(不能出现同名的参数);
在非严格模式下,如果函数在定义的时候,使用了多个同名的参数,则在函数内部形参的实际值为最后一个传入的实参值,严格模式下直接报错。
- arguments对象的行为不同,在非严格模式下修改形参的值会反映到arguments中,而严格模式下则相对独立。
1. 严格模式下,在函数内部修改了对象的指向,对arguments的值不会产生影响;
2. 在严格模式下,形参的值和arguments的值是相互独立的,在函数内部修改了形参的值对arguments不受影响;
3.在非严格模式下,修改了形参的值,arguments中的数据会跟着改变 - 禁用了argument.callee和caller函数:argument.callee是对函数自身的引用 argument.calller是对调用函数的引用。
- 不能在if语句中声明函数(会产生语法错误)
- 禁止使用eval和arguments作为标识符
- 修正this的值,在严格模式下,函数this的值始终是指定的值,无论指定的是什么值。
- 禁用了with语句
- 禁用了八进制
作用域
作用域:变量的作用范围就是它的作用域。
块级作用域:JavaScript中没有块级作用域。
词法作用域:在代码写好的那刻就已经确定作用域的;
- 在函数内部允许访问外部的变量;
- 只有函数可以限定作用域 ;
- 作用域规则首先使用提升变量;
- 如果当前作用域中有该变量,则不考虑外部作用域的同名变量。
动态作用域:变量的作用域由执行时的环境所决定;
说明:在js中不是动态作用域,当调用的时候,是往上查找的,不会到其他函数的作用域中去查找。
在JavaScript中唯一能够产生作用域的东西是函数
变量提升
JS中的代码执行分为两个步骤:
- 预解析:
JS在预解析阶段,会对使用var 关键字声明的变量和function声明的代码块进行提升操作,提升到当前作用域的顶端。 - 执行。
代码提升的几种情况
- 变量名相同:后面的会覆盖前面的;
- 函数名相同:后面的会覆盖前面的;
- 函数名和变量名相同的时候,理解为只提升函数的声明,不提升变量(和函数同名的变量);
4.函数表达式的提升:只会提升变量的声明 ,不会提升整一个函数。
注意点:变量和函数声明的提升只会提升到当前作用域的顶端。