JavaScript

JavaScript

编写位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>yzy</title>
<!-- 可以将代码写到外部文件中 -->
<!-- script 标签一旦用于引入外部 js 文件,当前 script 标签就不能再写 js 代码了 -->
<script type="text/javascript" src="path.js"></script>
<!-- 也可以直接写在内部 -->
<script type="text/javascript">
// js 按照从上到下顺序依次执行
// alert("浏览器弹窗");
// document.write("在 body 中写内容")
console.log("在浏览器控制台输出")
</script>
</head>
<body>
<button onclick="alert('可以将 js 代码写到标签的 onclick 属性中');">点我</button>
<a href="javascript:alert('可以将 js 代码写到超链接的 href 属性中')">点我</a>
</body>
</html>

基础语法

  • 严格区分大小写
  • 每一条语句已分号结尾
  • 声明变量: var、let
  • 数据类型(typeof var 可输出变量类型)
    • String
      • 使用双引号或者单引号都可以
      • 使用 \ 进行转义
        1
        var str = "hello";
    • Number
      • 包括整数和浮点数
      • Number.MAX_VALUE 表示 js 中的最大值
      • 如果数字超过了最大值,则会返回 Infinitely
      • NoN 也是 Number 类型
    • Boolean
      • true、false
    • Null
      • Null 类型的值只有一个,就是null(专门用于表示空对象)
      • 一般用于垃圾处理,不使用的对象手动赋值为 null
        1
        2
        var a = null;
        typeof a; // 会返回 Object 类型
    • Undefined
      • Undefined 类型的值只有一个,就是undefined(声明变量但是不赋值)
        1
        var a;
    • Object
  • 强制类型转换
    • 转换为 String
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      // 方式一:调用 toString() 方法
      var a = 123;
      a = a.toString(); // Number 转换为 String
      a = true;
      a = a.toString(); // Boolean 转换为 String
      a = null;
      a = a.toString(); // error
      a = undefined;
      a = a.toString(); // error (null 和 undefined 没有toString()方法)

      // 方式二:调用 String() 函数
      a = 123;
      a = String(a);
      a = null;
      a = String(a); // 正确的, 变成 "null"
      a = undefined;
      a = String(a); // 正确的, 变成 "undefined"
    • 转化为 Number
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      var a = "123"
      // 方式一:使用 Number() 函数
      a = Numner(a);
      // 如果字符串中有非数字,则转化为 NaN
      var a = "abc"
      a = Number(a); // a 变成 NaN
      // 如果字符串是空串或者全是空格,则转化为 0
      var a = "";
      a = Number(a); // a 变成 0
      // Boolean 只会变成 0 或 1
      var a = true;
      a = Number(a); // a 变成 1
      var a = false;
      a = Number(a); // a 变成 0
      // null 会变成 0
      var a = null;
      a = Number(a); // a 变成 0
      // undefined 会变成 NaN
      var a = undefined;
      a = Number(a); // a 变成 NaN

      // 方式二:parseInt()、parseFloat() 这两个函数可以将一个字符串中的有效数字取出来
      var a = "123px"
      a = parseInt(a); // a = 123
    • 转化为 Boolean
      1
      2
      3
      4
      5
      6
      7
      8
      // 调用 Boolean() 函数
      // 数字转 Boolean, 除了 0 和 NaN,其余都是 true
      // 字符串转 Boolean,除了空串都是 true
      // null 转换为 Boolean 是 false
      // undefined 转换为 Boolean 是 false
      // 对象也会转换为 true
      var a = 123;
      a = Boolean(a); // a = true;
  • 算数运算符
    • 当对非 Number 类型的值进行运算时,会将这些值转换为 Number 再运算
    • 任何值和 NaN 运算,结果都是 NaN
    • 两个字符串相加,会把两个字符串拼起来
    • 任何值和字符串做加法运算,都会先转换为字符串,然后再和字符串做拼串操作
      • 可以利用这一特点,将任意数据类型转换为 String,直接 + 一个 “”, 即可转换
        1
        2
        3
        result = 1 + 2 + "3"; // "33" 从左往右算
        result = "1" + 2 + 3; // "123"
        result = 100 - "1"; // 99 只有加法才会优先转为 String,其他都是转为 Number
  • 一元运算符
    • 正号不会对数字产生任何影响
    • 负号可以对数字进行取反
    • 对于非 Number 类型的值,会先转化为 Number,再运算
  • 逻辑运算符
    • &&
      1
      2
      3
      var a = 5 && 6; // a = 6;
      var a = 0 && 2; // a = 0;
      var a = 2 && 0; // a = 0;
    • ||
      1
      2
      3
      var a = 2 || 1; // a = 2;
      var a = 1 || 0; // a = 1;
      var a = 0 || 1; // a = 1;
  • 相等运算符
    • == 会做自动类型转换,=== 不会
  • 代码块
    • js 的代码块只具有分组作用(方便看,以及用于 if 语句),没有其他用途,代码块内部的内容,代码块外部是全部可见的
  • if 语句
    1
    2
    3
    4
    5
    6
    7
    8
    9
    if (条件) {

    }
    else if {

    }
    else {

    }
  • while 语句
    1
    2
    3
    4
    5
    6
    7
    while (条件) {

    }

    do {

    } while (条件);
  • for 语句
    1
    2
    3
    for (var i = 0; i < 10; ++i) {

    }

对象(一切皆是对象)

分类

  • 内建对象:Math、String、Number…
  • 宿主对象:有 js 运行环境提供,只要指由浏览器提供的对象(BOM、DOM)
  • 自定义对象

基本操作

1
2
3
4
5
6
7
8
9
10
11
12
13
var obj = new Object();
// 或者 var obj = {}; 创建对象
obj.name = 'yzy';
alert(obj.name);
// 也可以在创建时同时指定属性
var obj = {
name: 'yzy"
}
// 打印对象中的元素
for (var n in obj) {
console.log(n); // n 是对象的属性名
console.log(obj[n]); // 打印属性值
}
  • 全局变量是全局对象 window 的属性
  • 创建的函数都会成为 window 的方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var a = 1;
    console.log(a);
    console.log(window.a);

    function func() {
    alert();
    }
    func();
    window.func();
  • 使用 var 关键字声明的变量,会在所有的代码执行之前被声明,但是不会赋值
  • 使用函数声明形式创建的函数 function 函数(){} 会在所有的代码执行之前就被创建,所以可以在函数声明前调用函数
  • 使用函数表达式创建的函数,var func = function(){} 不会被声明提前,所以不能在声明前调用

函数

构造函数创建函数对象

1
2
3
4
var func = new Function();
console.log(typeof func); // 会打印 "function"
// 可以将封装的代码以字符串的形式传递给构造函数
var func = new Function("console.log('hello, this is my first function!');");

使用函数声明来创建函数

  • 语法:function 函数名(形参1、形参2、形参3…) { 函数体 }
    1
    2
    3
    4
    function func() {
    alert('hello');
    }
    func()

使用函数表达式创建函数

  • 语法:var 函数名 = function(形参1、形参2、形参3…) { 函数体 }
    1
    2
    3
    4
    var func = function() {
    alert("hello");
    }
    func();

函数的参数

  • 调用函数时解析器不会检查实参的类型
  • 调用函数时解析器不会检查实参的数量,多余的实参不会被赋值
  • 如果实参的数量少于形参的数量,则没有对应实参的形参是 undefined
    1
    2
    3
    4
    5
    function func(a, b) {
    console.log(a + b);
    }
    func(1, 2);
    func(1, 2, 3); // 3 没用
  • 实参也可以是一个函数
    1
    2
    // 这经常使用,将一个匿名函数传递给一个函数
    func(function(){alert("hello");})

函数的返回值

  • 使用 return var;
    1
    2
    3
    function func(a, b) {
    return a + b;
    }
  • 函数不 return,则会返回 undefined

立即执行函数

  • 函数定义完,立即被调用
    1
    2
    3
    (function(){
    alert('hello');
    })();

解析器在调用函数时,每次都会向函数内部传递一个隐含的参数 this

  • 以函数的形式调用时,this 永远都是 window
  • 以方法的形式调用时,this 就是调用方法的那个对象

工厂函数构建对象

1
2
3
4
5
6
function createObj(name, age) {
var obj = new Object();
obj.name = name;
obj.age = age;
}
var obj = createObj("yu", 18);

构造函数

  • 构造函数就是普通函数,不同的是习惯上首字母大写,且构造函数需要使用 new 关键字调用
    1
    2
    3
    4
    5
    function Person(name, age) {
    this.name = name;
    this.age = age;
    }
    var per = new Person("yu", 18);

构造函数执行流程

  • 立即创建一个新的对象
  • 将新建的对象设置为函数中的 this,在构造函数中可以使用 this 来引用新建的对象
  • 逐行执行函数中的代码
  • 将新建的对象作为返回值返回
使用instanceof 可以检查一个对象是否是一个类的实例
1
console.log(per instanceof Person); // 返回 true
  • 所有对象都是 Object 的后代,所有任何对象 instanceof Object 都返回 true

对象方法的创建

  • 直接在构造函数中定义方法,会导致每次 new 一个对象时,都会创建方法,浪费~
    1
    2
    3
    4
    5
    6
    7
    function Person(name, age) {
    this.name = name;
    this.age = age;
    this.func = function() {
    this.alert('hello');
    }
    }
  • 引用全局函数
    1
    2
    3
    4
    5
    6
    7
    8
    var func = function() {
    this.alert('hello');
    }
    function Person(name, age) {
    this.name = name;
    this.age = age;
    this.func = func;
    }
  • 引用全局函数当作对象方法会污染全局空间
    • 所创建的每一个函数,解析器都会向函数中添加一个属性 prototype,这个属性对应这一个对象,这个对象就是原型对象
    • 当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,可以通过 proto 来访问该属性
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      var func = function() {
      this.alert('hello');
      }
      function Person(name, age) {
      this.name = name;
      this.age = age;
      this.func = func;
      }
      console.log(Person.prototype);
      var per = new Person("yu", 18);
      console.log(per.__proto__); // 和 Person.prototype 的值相同
    • 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象
      • 可以将对象中的共有内容,统一设置到原型对象中
        1
        2
        3
        4
        5
        6
        function Person(name, age) {
        this.name = name;
        this.age = age;
        this.func = func;
        }
        Person.prototype.a = 123; // 向 Person 类的原型对象中添加属性 a
    • 创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,不用分别为每一个对象添加,也不会影响到全局作用域
    • 原型对象也是对象,所以它也有原型
    • Object 是所有对象的原型
    • 当我们在页面中直接打印一个对象时,实际上是输出对象的 toString() 方法的返回值

函数的方法

  • call() 和 apply()
    • 这两个方法都是函数对象的方法,需要通过函数对象来调用
    • 当对函数调用 call() 和 apply() 都会调用函数执行
    • 在调用 call() 和 apply() 可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行的this
  • this 的情况
    • 以函数形式调用时,this 永远都是 window
    • 以方法的形式调用时,this 是调用方法的对象
    • 以构造函数的形式调用时,this 是新建的那个对象
    • 使用 call() 和 apply() 调用时,this 是指定的那个对象

函数隐含参数

  • 在调用函数时,浏览器每次都会传递两个隐含的参数
    • 函数的上下文对象 this
    • 封装实参的对象 arguments
      • arguments 是一个类数组对象,它可以通过索引来操作数据(arguments[0],arguments[1],…),也可以获取长度(arguments.length)
      • 在调用函数时,所传的实参都会在 arguments 中保存

数组 (Array)

  • 数组也是一个对象

    1
    2
    3
    4
    5
    6
    var arr = new Array();
    // var arr = []; // 也可以
    // 添加元素
    arr[0] = 0;
    arr[1] = 1;
    arr[10] = 10;
  • 读取索引范围外会返回 undefined

  • 使用 arr.length 获取元素个数

    • 对于连续的数组,length 得到数组的长度
    • 对于非连续的数组,length 得到数组最大的索引 + 1
      • 创建非连续的数组,浪费空间,尽量创建连续数组
  • 修改 length 的值会截断数组的值(多了截断,少了填充)

  • 像数组最后一个位置添加元素

    1
    arr[arr.length] = 值
  • 使用字面量创建数组,可以在创建时指定数组中的元素

    1
    2
    3
    4
    5
    var arr = [1, 2, 3];
    var arr = new Array(1, 2, 3);

    var arr = [10]; // 创建只有一个元素的数组
    var arr = new Array(10); // 创建 10 个元素的数组
  • 数组中的元素可以是任意类型

    1
    var arr = [1, "hello", [1,2,3]];
  • push 方法向数组末尾添加一个或多个元素,返回数组的新长度

  • unshift 方法向数组开头添加一个或多个元素,返回数组的新长度

  • pop 方法删除数组最后一个元素,并将删除的元素返回

  • shift 方法删除数组第一个元素,并将删除的元素返回

  • forEach() 方法便利数组,需要一个函数作为参数(IE8 以上的浏览器才支持)

    • 第一个参数:当前正在遍历的元素
    • 第二个参数:正在遍历的元素的索引
    • 第三个参数:正在遍历的数组
      1
      2
      3
      arr.forEach(function(value, index, obj){
      console.log(a);
      })
  • arr.slice(start, end): 从数组提取指定元素

    • 左闭右开
    • end 可以省略不写,默认是末尾
    • 索引可以传递负值
  • arr.splice(start, end, arg1, arg2,…): 删除数组中的指定元素,还可以添加一些新元素(插入 start 位置),并将被删的元素返回

  • arr.concat(arr1, arr2, arr3,…): 连接两个数组,并将新数组返回,不会对原数组产生影响

  • arr.join(连接符): 将数组转化为字符串,不会影响原数组

  • arr.reverse(): 反转数组,直接修改原数组

  • arr.sort(): 影响原数组

    • 默认从小到大,可以传入函数自定义(返回大于 0,则交换位置;返回小于等于0,不交换位置)

Date 对象

1
var d = new Date();

Math

  • Math 和其他的对象不同,它不是一个构造函数
  • 属于一个工具类,不用创建对象
    1
    2
    console.log(Math.PI);
    console.log(Math.random());

字符串的方法

正则表达式

1
2
3
4
5
6
7
// 创建正则表达式对象
var 变量 = new RegExp("正则表达式", "匹配模式");

var reg = new RegExp("a", "i");
// var reg = /a/i;
var str = "a";
var result = reg.test(str); // 测试表达式是否满足规则

字符串与正则表达式

DOM(Document Object Model)

  • js 中通过 DOM 来对 html 文档进行操作

事件

  • 用户和浏览器之间的交互行为:点击按钮、鼠标移动、关闭窗口…
  • 可以在事件对应的属性中设置一些 js 代码,这样当事件被触发时,这些代码会执行
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>yzy</title>
    </head>
    <body>
    <!-- <button id="btn" onclick="alert('hello');">我是一个按钮</button> -->
    <button id="btn">我是一个按钮</button>
    </body>
    <script type="text/javascript">
    var btn = document.getElementById("btn");
    btn.onclick = function() {
    alert('yu');
    }
    </script>
    </html>

鼠标

  • 元素.onmousemove = function(event){}
    • 当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数
    • event.clientX \ event.clientY (鼠标坐标位置)

事件的冒泡

  • 指事件的向上传导,当后代元素上的事件被触发时,其祖先的相同事件也会触发
  • 可以将事件对象的cancelBubble 设置为 true,可以取消冒泡

键盘

  • document.onkeydown = function(event){}
  • document.onkeyup = function(event){}

文档的加载

  • 浏览器加载一个页面时,是按照自上向下的顺序加载的,读取一行就执行一行
  • onload 事件会在这个页面加载完成之后触发(window.onload = function(){})

选择元素

  • document.getElementById(“…”)…
  • document.querySelector(“…”) 可以根据 css 选择器进行选择
    • 使用该方法总会返回唯一的一个元素,如果满足条件的元素有多个,那么它只会返回第一个
    • document.querySelectorAll(“…”)可以选择所有并装到数组中

DOM 增删改

  • var p = documents.createElement(“p”)
    • 创建一个元素节点对象,需要一个标签名作为参数
  • var text = documents.createTextNode(“text”)
    • 创建一个文本节点对象,需要一个文本内容作为参数
  • p.appendChild(text)
    • 向一个父节点加一个子节点
  • 最后还需要把创建的节点插入到已有的 html 节点中

  • removeChild()

  • replaceChild()

BOM(Brower Object Model)

  • BOM 使我们可以通过 js 操作浏览器
    • Window
      • 代表整个浏览器的窗口,同时 window 也是网页中的全局对象
      • 其他 BOM 对象在浏览器中都是作为 window 对象的属性保存的,可以通过 window 对象来使用,也可以直接使用
    • Navigator
      • 代表当前浏览器的信息,通过该对象可以识别不同的浏览器
        • console.log(navigator.userAgent)
    • Location
      • 代表当前浏览器的地址信息,可以获取浏览器地址信息或者操作浏览器跳转页面
    • History
      • 代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录
        • 由于隐私原因,该对象不能获取具体的历史记录,只能操作浏览器向前或者向后
        • 且该操作只在当次访问有效
    • Screen
      • 代表用户的屏幕信息,通过该对象可以获取到用户的显示器的相关信息
  • 定时调用:setInterval(function(){}, timeValue)
  • 延时调用:setTimeout(function(){}, timeValue) 只会调用一次

json(javascript objet notation, js 对象表示法)

  • json 和 js 对象的格式一样,只不过 json 字符串中的属性必须加双引号
  • json –> js 对象
    • var obj = JSON.parse(json)
  • js 对象 –> json
    • var s = JSON.stringify(obj)
  • eval() 这个函数可以用来执行一段字符串形式的 js 代码,并将执行结果返回

关于引用变量赋值的问题

  • 2 个引用变量指向同一个对象,通过一个变量修改对象内部的数据,另一个变量看到的是修改之后的数据
  • 2 个引用变量指向同一个对象,让其中一个引用变量指向另一个对象,另一个引用变量依然指向前一个对象