JavaScript 入门
Posted 脑子是个好东西,出门得带上 __rongge
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
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
就是新创建的那个对象 -
使用
call
和apply
调用时,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(); //唐僧
构造函数
-
构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上会将首字母大写
-
构造函数与普通函数的区别就是调用方式的不同:
-
普通函数是直接调用
-
构造函数需要使用关键字
new
来调用
-
-
构造函数的执行流程:
-
立刻创建一个新对象
-
将新建的对象设置为函数中的
this
,在构造函数中可以使用this
来引用新建的对象 -
逐行执行函数中的代码
-
将新建的对象作为返回值返回
-
-
构造函数就是一个类,其创建的对象称之为该类的实例
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
例子:利用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);
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
以上是关于JavaScript 入门的主要内容,如果未能解决你的问题,请参考以下文章