JavaScript 入门

函数对象方法

call()apply()

  • 这两个方法都是函数对象的方法,需要通过函数对象来调用

  • 当对函数调用call()apply()方法时,同通过函数名调用函数,都会使函数执行,并且结果一样

  • 在调用call()apply()方法时,可以将一个对象指定为第一个参数,那这个对象就会成为函数执行时的this

  • call()方法可以将在对象之后的实参依次传入

  • apply()方法则需要将实参封装到一个数组中传入

// 无参
function func() {
    alert(this);
}
​
var obj = {
    name:'obj',
    infoName:function() {
        alert(this.name);
    }
};
​
func.call();        // [object Window]
func.call(obj);     // [object Object]
func.apply(obj);    // [object Object]
obj.infoName.call(obj);     // obj  
//------------------------------------------------------------------------------------
// 有参
function func(a, b) {
    console.log('a =' + a);
    console.log('b =' + b);
}
​
var obj = {
    name:'obj',
    infoName:function() {
        alert(this.name);
    }
};
​
// 没有参数传入时
func.call(obj);     // a =undefined  b =undefined
func.apply(obj);    // a =undefined  b =undefined
// 为函数传入实参时
func.call(obj,2,3);     // a=2 b=3  
func.apply(obj,[2,3]);      // a=2 b=3
eg

JS 作用域

全局作用域

窗口打开时创建,关闭时销毁

  • 在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,由浏览器创建,我们可以直接使用

  • 在全局作用域中:

    • 创建的变量都会作为window对象的属性保存!!

    • 创建的函数都会作为window对象的方法保存!!

var a = 10;
console.log(window.a);  //得到的结果是--10
​
function fun() {
    console.log('我是fun函数');
}
window.fun();   //执行结果--我是fun函数

函数(局部)作用域

调用函数时创建,函数执行结束后销毁

  • 在函数作用域中能访问到所有的全局变量

  • 而在全局作用域中则无法访问到函数中的变量

  • 变量(作用域)查找:

    • 从当前所在的位置开始,往上一级查找,即: 局部-->局部-->。。。-->全局

    • 函数中想访问全局的变量可以使用window对象,如:window.a

    • 在函数作用域中也有变量的声明提前特性:

      • 使用var关键字声明的变量,会在函数中所有的代码执行之前被声明

      • 函数声明也会在函数中所有的代码执行之前执行

函数的声明提前

  • 使用函数声明形式创建的函数,即 : function func () {},它会在所有的代码执行之前就被创建,所以我们可以在函数声明之前调用函数

  • 使用函数表达式创建的函数,即 :var func = function () {},它不会被声明提前,所以不能在声明之前调用

this

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

  • 它指向的是一个对象,即 上下文对象
  • 根据调用方式的不同,this会指向不同的对象
    • 以函数的形式调用时,this永远都是window

    • 以方法的形式调用时,this就是调用方法的那个对象

    • 以构造函数调用时,this就是新创建的那个对象

    • 使用callapply调用时,this是指定的那个对象

例子

//创建一个name变量
var name = '全局';
​
//创建一个fun函数
function fun() {
    console.log(this.name);
}
​
//创建两个对象
var obj = {
    name:'孙悟空',
    infoName:fun
};
var obj1 = {
    name:'唐僧',
    infoName:fun
}
​
fun();  //全局
obj.infoName();     //孙悟空
obj1.infoName();    //唐僧
View Code

构造函数

  • 构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上会将首字母大写

  • 构造函数与普通函数的区别就是调用方式的不同:

    • 普通函数是直接调用

    • 构造函数需要使用关键字new来调用

  • 构造函数的执行流程:

    1. 立刻创建一个新对象

    2. 将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象

    3. 逐行执行函数中的代码

    4. 将新建的对象作为返回值返回

  • 构造函数就是一个类,其创建的对象称之为该类的实例

function Person(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.infoName = function() {
        alert(this.name)
    }
}
​
var obj = new Person('红孩儿', 15, '男');
console.log(obj);

但是有个问题是:

  • Person构造函数中,为每一个对象都添加一个infoName方法。也就是说构造函数每执行一次就会创建一个新的infoName方法,也就是说每一个实例的infoName都是唯一的,这会造成内存浪费,于是我们可以将infoName方法定义在全局,这样就可以避免重复的创建新方法,但是为了不造成全局变量污染,建议慎用!!

function Person(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.infoName = func;
    }
// 在全局定义函数方法然后赋值给infoName
function func() {
        alert(this.name);
    };
var obj = new Person('红孩儿', 15, '男');
var obj1 = new Person('jack', 25, '男');
​
console.log(obj.infoName == obj1.infoName);     // true

那怎么处理上述这个问题呢???即原型对象!!

原型(prototype)

  • 创建一个函数,解析器都会向函数中添加一个属性prototype,该属性对应一个对象,即原型对象

  • 当一个函数作为普通函数调用prototype时,没有任何作用

  • 当一个函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__来访问该属性

  • 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象

  • 我们可以将对象中共有的内容统一设置到原型对象中

属性查找

当我们访问对象的一个属性或方法时,它会先从自身中查找,如果有则直接使用,如果没有则会去原型对象中查找,找到则直接使用,如果没有则会去原型的原型中查找,直到找到Object对象的原型,如果Object对象的原型都没有找到,则返回undefined!

function MyClass() {
   alert('hello');
}
​
// 向MyClass的原型中添加属性a
MyClass.prototype.a = 123;
​
// 向MyClass的原型中添加方法func
MyClass.prototype.infoName = function() {
    alert('hello world');
}
​
// 创建MyClass的实例
var mc = new MyClass();
var mc1 = new MyClass();
console.log(mc.__proto__ == MyClass.prototype);     // true
​
// 向mc中添加属性a
mc.a = '我是mc中的a';
​
// 如果自己没有,原型中也没有,则会返回undefined
console.log(mc.b);
​
// Object原型没原型,找到最后会返回null
console.log(mc.__proto__.__proto__.__proto__);

那上述的全局变量污染问题就可以用原型解决了!!

function Person(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
    }
​
// 向原型中添加infoName方法
Person.prototype.infoName = function func() {
    alert(this.name);
    };
​
var obj = new Person('红孩儿', 15, '男');
var obj1 = new Person('jack', 25, '男');
​
console.log(obj.infoName == obj1.infoName);     // true

Date

  • 时间戳:getTime(),毫秒数

eg: //等待3秒之后执行
var startTime = new Date().getTime();
var stopTime = new Date().getTime();
while (stopTime - startTime < 3000) {
    startTime = new.Date().getTime();
}
  • 常用方法

    • 获取 年月日时分秒

事件

事件的绑定与移除须指向同一个方法(地址)

  • 绑定:

//on事件
div.onclick = function() {
    
}
​
// 非on事件
var fn = function() {
​
}
div.addEleventListener('click',fn);
  • 解绑:

//on事件
div.onclick = null;
s
//非on事件
div.removeEleventListener('click',fn);
  • addElementLister()

    • 可以为元素绑定相应函数,可以同时为一个元素的相同事件绑定的多个响应函数,并且会被按顺序执行(不支持IE8及以下)

    • 参数:

      • 事件的字符串,不要on

      • 回调函数,当事件触发时该函数会被调用
      • 是否在捕获阶段触发事件,需要一个布尔值,一般都传入false

默认事件

  eg:鼠标邮件时会弹出菜单栏!!

取消默认

sub.oncontextmenu = function(ev) {
    // 方法一:
    ev.preventDefault();
    // 方法二:
    return false;
}

鼠标事件

  • 鼠标移动:

div.onmousemove = function(ev) {
    ev.clientX; //获取X坐标
    ev.clientY; //获取Y坐标
}

键盘事件

一般绑定给文档(document)

var div = document.querySelector('div');
document.onkeydown = function(ev) {
    console.log(ev.keyCode);    // 打印对应的键盘编码
}
// 移动div
switch(ev.keyCode) {
    case 37:
        div.style.left = div.offsetLeft - 3 + 'px'; 
        break;
    case 38:
        div.style.top = div.offsetTop - 3 + 'px';
        break;
}

冒泡

  • 父子级拥有同样的事件,在子级区域触发事件,父级也能捕获并响应

  • 阻止冒泡:

sub.onclick = function(ev) {
    // 方法一:
    ev.stopPropagation();
    // 方法二:
    ev.cancelBubble = true;
}

for循环语句及执行流程

for循环语法:

for(①初始化表达式; ②条件表达式; ④更新表达式) {
    ③语句、、、
}
for(var i = 0; i < 10; i++ ) {
    alert(i);
}

for循环执行流程:

  • 1. 执行初始化表达式,初始化变量
  • 2. 执行条件表达式,判断是否满足条件执行循环
    • 如果判断结果为true,则执行循环③
    • 如果为false,则终止循环
  • 3. 行更新表达式,执行完毕后继续重复第二步

# 注意:

  • for循环中的三个表达式都可以省略,也可以写在外部

  • 如果在for循环中不写任何表达式,那此时该循环就是一个死循环

for(; ; ) {
    alert('hello');
}   // 会一直执行下去

for循环只写一个条件表达式和初始化表达式时,可以实现while循环的作用

var i = 0;
for(; i < 10; ) {
    alert(i++);
}

数组(Array)

push() 末尾添加

  • 该方法可以向数组的末尾添加至少一个元素,并返回数组的新的长度

  • 可以将要添加的元素作为方法的参数传递,这样这些元素会自动添加到数组的末尾

var arr = ['jack','Bob','alina'];
var res = arr.push('peter','zero');
console.log(arr);   // ["jack", "Bob", "alina", "peter", "zero"]
console.log(res);   // 5

unshift() 从头添加

  • 该方法会向数组开头添加至少一个元素,并返回新数组的长度

res = arr.unshift('李哥','牛哥');
console.log(arr);   // ["李哥", "牛哥", "jack", "Bob", "alina", "peter", "zero"]
console.log(res);   // 7

pop() 删除最后一个值

  • 该方法可以删除数组的最后一个元素,并将被删除的元素当做返回值返回

// 接收返回值 res
res = arr.pop();
console.log(arr);   // ["jack", "Bob", "alina", "peter"]
console.log(res);   // zero

shift() 删除第一个值

  • 该方法可以删除数组的第一个元素,并将被删除的元素当做返回

res = arr.shift();
console.log(arr);
console.log(res);

for循环 遍历取值

  • 循环将数组的值取出来

var arr = ['孙悟空','唐僧','沙僧'];
for(var i=0; i < arr.length; i++) {
    console.log(arr[i]);
}

forEach() 遍历取值

类似于for循环,但是forEach只支持IE8以上的浏览器,一般用于移动端开发

  • 该方法需要一个函数作为参数,由我们创建,但不是由我们调用的,即回调函数

  • 数组中有几个元素,函数就会执行几次,每次执行时,浏览器会将遍历到的元素以实参的形式传递进来,所以我们可以定义形参,来读取这些内容

  • 浏览器在回调函数中传递的三个参数:

    • 第一个参数:当前正在遍历的元素

    • 第二个参数:当前正在遍历的元素的索引

    • 第三个参数:当前正在遍历的数组

var arr = ['孙悟空','唐僧','沙僧','猪八戒'];
arr.forEach(function(value, index, obj) {
    console.log(value);
});

slice() 取出指定位置元素

  • 可以用来从数组提取指定的元素,并且不会改变元素数组,而是将截取到的元素装到一个新的数组中返回

  • 参数:

    • 参数1:截取开始位置的索引

    • 参数2:截取结束位置的索引

      • 结束索引可省略,表示从开始位置到数组结尾全部取出

      • 也可以传递一个负值,即代表从数组后面往前计算,-1即倒数第一个、-2倒数第二个、。。。

var arr = ['孙悟空','唐僧','沙僧','猪八戒'];
var res = arr.slice(0,2);   // 顾头不顾尾
console.log(res);   // ["孙悟空", "唐僧"]
console.log(res == arr);    // false

splice() 删除指定位置元素

  • 从数组中删除指定的元素,会影响到原数组,将指定的元素从原数组删除,并返回删除的元素

  • 参数:

    • 参数1:表示起始位置的索引

    • 参数2:表示删除的元素数量

    • 参数3:可传入新元素,并且新元素会自动插入到开始位置索引的前边

var arr = ['孙悟空','唐僧','沙僧','猪八戒'];
var res = arr.splice(1,2);  
// 删除元素
console.log(res);   // ['唐僧','沙僧']
// 添加新元素
res = arr.splice(0,2,'jack','peter');
console.log(arr);   // ["jack", "peter", "沙僧", "猪八戒"]
​
console.log(res == arr);    // false
eg

例子:利用splice实现数组去重

var arr = [1,3,5,2,4,3,2,2,6,7];
// 先循环数组中的每一个值
for(var i=0; i < arr.length; i++) {
    // 获取当前元素后的所有元素
    for(var j=i+1; j < arr.length; j++) {
        // 判断i和j两个元素的值是否相等
        if(arr[i] == arr[j]) {
            // 相等,则说明值重复,应该删除最后一个
            arr.splice(j,1);
            // 删除了当前j所在的元素后,j后边的元素会自动补位,此时就不会再次比较该位置的元素
            // 所以在下一次比较前让j自减一次
            j --;
        }
    }
}
console.log(arr);
View Code

concat() 拼接

  • 可以连接至少两个数组或者元素,并将新的数组返回,该方法不会对原数组产生影响

join() 拼接为字符串

  • 该方法可以将数组转换为一个字符串,不会对原数组产生影响,而是将转换后的字符串作为结果返回

  • join()的参数是字符串类型,如果不指定连接符,则默认使用,连接

var arr = ['jack','peter','bob'];
var res = arr.join('-');
console.log(res);   // jack-peter-bob

reverse() 反转

  • 数组反转,会直接修改原数组

var arr = ['jack','peter','bob'];
arr.reverse();
console.log(arr);   // ["bob", "peter", "jack"]

sort() 排序

  • 可以对数组的元素进行排序,会影响原值,默认是按照Unicode编码进行排序

  • 对于纯数字的数组排序时,可以添加一个回调函数来实现自定义排序

  • 浏览器会根据回调函数的返回值来决定元素的顺序:

    • 如果返回值大于0,则会交换元素的位置

    • 如果返回值小于0,则不会交换元素位置

    • 如果返回值为0,也不会交换位置

var arr = [1,3,5,2,7,11];
arr.sort(function(a, b) {
    return a - b;
})
console.log(arr);   // 1,2,3,5,7,11

字符串(String)

底层原理是以数组的形式保存的

length 长度

  • 属性值!字符串的长度

var str = 'hello';
console.log(str.length);    // 5

concat() 拼接

  • 可以连接两个以上的字符串,作用和+一样

indexOf() 正向索引

  • 该方法可以检索一个字符串中是否含有指定的字符,从前往后找

    • 有,则返回该字符出现的第一次的索引值,也可指定查找的起始位置

    • 没有,则返回-1

var str = 'hello jack,how are you';
var res = str.indexOf('h');     // 0
res = str.indexOf('h',3);   // 11
console.log(res);

lastIndexOf() 反向索引

  • 用法同indexOf()一样,不过lastIndexOf()是从后往前找

  • 也可指定起始的查找位置

substring() 截取

  • 用来截取一个字符串,和slice()相似,顾头不顾尾

  • 参数:

    • 第一个:起始位置的索引

    • 第二个:结束位置的索引

  • 注意:

    • 该方法不能接收负值作为参数,如果传入一个负值,则默认使用0

    • 并且当第二个参数小于第一个参数时,会自动交换两个参数的位置

var str = 'please hold on';
// 自动交换参数的位置
console.log(str.substring(2,0));    // pl

charAt() 索引取值

  • 按索引取值

var str = 'hello';
console.log(str.charAt(3)); // l

charCodeAt() 查看字符编码Unicode

  • 获取指定位置字符串的字符编码(Unicode编码)

var str = 'hello';
console.log(str.charCodeAt(1)); // 101

fromCharCode() 从Unicode查看对应字符

  • 可以根据字符编码获取字符,但必须通过构造函数对象String调用

console.log(String.fromCharCode(101));  // e
console.log(String.fromCharCode(20013));    // 中

split() 切分

  • 将一个字符串切分为一个数组

  • 参数:字符串类型,并会根据该字符串去切分为数组

var str = 'bob,jack,peter,lee';
console.log(str.split(','));

正则

  • 语法:

var 变量名 = new RegExp('正则表达式','匹配模式');   // 构造函数
var 变量名 = /正则表达式/匹配模式;  // 字面量
  • 匹配模式:

    • i 不区分大小写

    • g 全局匹配

    • m 多行匹配

元字符

量词

正则方法

match()

  • 可根据正则表达式将符合条件的内容匹配到
  • 默认只匹配一次,匹配到就停止检索,并将匹配到的结果以数组的形式返回
var str = '1a2b3c4d5e6D7G9';
var res = str.match(/[a-z]/ig);
console.log(res);   // ["a", "b", "c", "d", "e", "D", "G"]

 

search()

  • 检索字符串是否含有指定的内容,并且只会找到第一个

  • 检索到内容,则返回第一次出现的索引

  • 检索不到内容,返回-1

var res = 'you looked so good';
console.log(res.search(/[A-z]oo[a-z]/));    // 4

replace()

  • 可以将字符串中指定的内容替换为新的内容,返回字符串类型,默认只替换一个

  • 参数:

    • 第一个参数:被替换的内容,可以是正则表达式

    • 第二个参数:新内容

var str = 'hello jack how are you';
console.log(str.replace(/o/g,'@'));     // hell@ jack h@w are y@u
​
// 删除所有字母
var str = '1A2b3c4d5e6F7H'
console.log(str.replace(/[a-z]/ig,''));     // 1234567

split()

  • 参数可以传入一个正则表达式,比字符串的切分更加灵活

var str = 'a2b5c1F6d7';
console.log(str.split(/[A-z]/));

DOM

DOM(document object model),文档对象模型

<button id='btn'>我是一个按钮<button>
    
<script>
    // 获取到一个对象
    var btn = document.getElementById('btn');
​
    // 修改对象的内容
    btn.innerHTML = "I'm a button";
</script>

获取元素节点

通过document对象调用

1. getElementById()       // 通过id属性获取一个元素节点对象
2. getElementsByTagName() // 通过标签名获取一组元素节点对象
3. getElementsByName()    // 通过name属性获取一组元素节点对象

获取元素节点的子节点

通过具体的元素节点调用

1. getElementsByTagName()  // 方法,返回当前节点的指定标签名后代节点
2. childNodes   // 属性,表示当前节点的所有子节点
                // 注意:childNodes属性会获取包括文本节点在内的所有节点,空白符也会被当做节点处理
    children // 属性,可以获取当前元素的所有子元素(建议使用)
3. firstChild         // 属性,表示当前节点的第一个子节点
   firstElementChild  // 属性,获取当前节点的第一个子元素
                      // 不支持IE8及以下
4. listChild    // 属性,表示当前节点的最后一个子节点

jQuery

原文地址:https://www.cnblogs.com/rongge95500/p/9903269.html