一、 JS代码运行环境
js代码是通过<script>标签直接嵌入页面中的,一个页面中可以有多段<script>定义的代码片段 它们既相互关联 又保持独立(角度不同)
关联性:一段script中的内容(变量、函数) 可以在另一段script中使用
独立性:一段script运行发生错误 不影响另一script的执行
1、全局执行环境
js在运行时 首先会创建一个全局执行环境 这个全局环境就是定义一个全局对象,页面中所有的内容(不同的script中的内容) 都是这个全局对象的属性,在浏览器javascript中(嵌入网页的js)这个全局对象是window。
// 定义变量
var bar = "some text";
// 定义函数
function(){
console.log("hello world");
}
// 查看网页中的全局对象
console.log(window);
window全局对象的属性.png
这就是说 不同的script中的内容 都同属一个window对象 因此他们的内容可以共享。
<script>
// 定义变量
var bar = "some text";
// 定义函数
function(){
console.log("hello world");
}
// 查看网页中的全局对象
console.log(window);
</script>
<script>
// 打印不同script标签里的变量
console.log(bar);
// 调用不同script标签里的函数
foo();
</script>
2、运行错误
1、当发生编译错误时 代码不执行 而执行时的错误;
2、影响错误之后的的输出 而不影响前面代码的执行。
3、无论发生何种错误 一段代码发生了错误不影响另一段代码的运行。
<script>
// 错误之前输出
console.log("编译错误之前的输出");
// js代码可以不以";"结尾 它会自动补全
// 非法换行,编译时发生语法错误
var bar = "hello
world";
console.log("编译错误之后的输出");
</script>
<script>
console.log("执行错误之前的输出");
console.log(unknow);
console.log("执行错误之后的输出");
</script>
3、使用异常处理错误
js代码运行时的错误 在页面不显示。而是自动抛出一个错误对象(Error)
处理错误:
1、使用try/catch来捕获该错误对象。
2、自定义错误处理场景 使用throw new Error(‘提示信息’)手动抛出错误。
try {
//当执行发生错误时 会抛出一个ReferenceError错误对象
console.log(unknow);
} catch (e) {
console.log(e);
//查看错误提示信息 ->
console.log(e.message);
}
function division(x) {
if (!x) throw new Error("被除数不能为0");
return 1/x;
}
try {
division(0);
} catch (e) {
console.log(e.message);
}
</script>
二、 变量和作用域
1、变量是存储数据的容器,JS中变量使用var声明,与变量密切相关的是它的作用域。作用域是指变量作用的区域 它分为全局和局部的作用域。
2、定义在程序顶层(不属于某个函数)中的变量是全局变量,函数体内的变量为局部变量。全局变量在整个页面中都有效,局部变量只能做作用于函数体内 当函数退出(执行完毕、调用结束)时 函数体内的状态会被销毁掉(变量被删除了) 因此无法在外部访问到。
3、变量也可不用var声明 未经var声明的变量会成为全局变量 即使是定义在函数体内。
4、使用var声明 但是未赋值的变量 初始化值是undefined。
5、没有块状作用域
<script>
//常见面试题
function foo() {
var scope;
//函数体内的变量没有块状的作用域 变量一经定义 在整个函数体内都有效
console.log(scope);
scope = "local";
}
foo();
</script>
6、作用域链
全局变量是全局对象的属性 局部变量是一个叫做激活对象(也叫调用对象 是函数调用时产生的对象)的属性。组成变量作用域的是一个对象列表或对象链 一般叫“作用域链”。
在程序顶层中变量作用域链为全局对象,定义在函数f体内的变量作用域链为 f的激活对象 => 全局对象,函数体内嵌套的函数g的作用域为 g的激活对象 => 外围函数f的激活对象 => 全局对象。
当查询变量x值时 JS会沿着它当前所在位置的作用域链的头部开始查找 如果找到 则返回结果 如果没有 则继续往下查找 直到根部(根没有则是undefined)。
三、数据类型
布尔值、字符串、数值、null、undefined等是基本类型数据,传值引用;
数组、函数和对象是引用类型,传地址引用。
四、运算符和表达式
1、typeof
使用typeof 查看变量的数据类型 它是一个运算符 不是函数 当查看一个表达式时 会使用()使之看起来像个函数。
var arr = [];
arr[0] = "z";
console.log(typeof arr); // object
console.log(typeof 1); //number
console.log(typeof "hello"); //string
console.log(typeof true); //boolean
console.log(1 + "a"); //数值和字符串相加 是将数值转化成字符串"1"
console.log(typeof (1 + "a")); //string
2、delete
可以删除一个对象的属性或者数组元素。
还可以用来删除一个未用var声明的变量。
3、instanceof
用来检测一个对象是否是某个类的实例 注意不要取检测是否是Object的实例(都是true)。
4、in
用来判断对象中是否有某个属性
5、with 语句
变量有作用域 当作用域比较长的时候 可以使用with修改作用域链的头 简化代码输入量。
<body>
<div id="d"></div>
<script>
var d = document.getElementById("d");
with (d.style) {
width = 100 + "px";
height = 100 + "px";
backgroundColor = "green";
}
</script>
</body>
6、|| 运算
或运算执行时 当表达式两边都为false时 返回false,有一个为true就返回true。
短路运算:当左边为true时 直接返回左边的值 不用往后执行。如果左边为FALSE呢 右边代表最终的结果。
五、函数
1、函数参数
JS中的函数参数可以不严格的匹配 当调用时传入的实参个数 多余定义的形参 多出的值会被忽略 当实参个数少于形参 在函数体内的形参值为undefined。
<script>
function f(x, y) {
console.log(x,y);
}
f(1,2);
f(1,2,3);
f(1);
</script>
2、arguments对象
函数体内标识符arguments有着特殊的含义 它是一个类似数组的对象 用来获取函数调用时传入的实参值。
function h(x, y) {
//函数体内使用arguments查看传入的实参
console.log(arguments);
//arguments对象的数字下标存储了实参值
console.log(arguments[0], arguments[1]);
//arguments的length属性存放实参个数
console.log(arguments.length);
}
h("hello","world");
arguments对象可以有效的帮助我们处理可变参数(参数长度不固定 没法定义形参接收)函数,例如 计算一组数的最大值 实际调用时 会有不同个数的参数传入。
max(1,2,3,4)
max(1,2)
max(1,2,3)
<script>
//使用arguments来处理可变参数的函数
function max() {
//不定义形参 使用arguments来获取实际调用时的参数值
//初始化最大值为第一个实参元素
var m = arguments[0];
//从第二个实参值开始 循环 判断
for (var i = 1; i < arguments.length; i++) {
if (m < arguments[i]) m = arguments[i];
}
return m;
}
console.log(max(1,2,3));
console.log(max(1,2,3,4));
console.log(max(1,2,3,4,5));
</script>
3、函数属性
函数是数据类型 是对象的数据类型,它有属性和方法,函数的length属性是查看函数形参的个数。
function g(x, y) {
//函数的length属性是它定义的形参个数
console.log(g.length);
}
g();
网友评论