JavaScript基础知识总结(一)
1. 异步加载
在加载网页时,用户会先看到页面的内容,而如果js要加载的东西过多时,页面并不会显示内容,而是空白的这样用户体验会大打折扣,所以这里可以在 script 标签内添加属性来异步完成加载 JavaScript 。
<script src="test.js" async></script>
2. 延迟执行
有些 js 代码中会调用 HTML 代码中 id 对应的元素,但是HTML 页面加载是从上到下的,这时如果 js 代码中要用到的话,就需要写到 HTML 的尾部,这里也可以在 script 标签内添加属性来延迟执行 js 文件。
<script src="test.js" defer></script>
3. 字符串加减
var a="3.1415926535";
var b = a - 2;
var c = a + 2;
alert(b+"\n"+c);
乍一看 b = 1.1415926535,c = 5.1415926535,我们来看输出结果:
字符串不支持减法,所以 a 变量被改变数据类型为数值类型,执行 a- 2=1.14159
但是字符串支持加法运算,加法作为连字符,所以系统吧 c 变量变为字符串,连了起来 c = a+2=......2
4. 定义全局变量与局部变量
//定义全局变量,这里不管用不用var都是全局变量
var test="全局变量";
function myFun(){
//在函数内的不使用var定义的变量为全局变量
age = 20
//在函数内使用var定义的变量为局部变量
var isMale = true;
}
myFun();
alert(test +"\n" + age);
alser(isMale);
如果同名,则局部变量将会覆盖全局变量
var isMale="全局变量";
function myFun(){
var isMale ="局部变量";
alert(isMale);
}
myFun();
alert(isMale);
第一次输出为“局部变量”第二次输出为“全局变量”
下面这样会覆盖掉
var isMale="全局变量";
function myFun(){
isMale ="局部变量";
alert(isMale);
}
myFun();
alert(isMale);
第一次输出为“局部变量”第二次输出为“局部变量”
补充:
var 定义变量没有块的概念
let 定义变量,有作用域,即块的概念
5. 变量提升
var scope="全局变量";
function test(){
document.writeln(scope + "<br/>");
//定义scpoe局部变量,其作用范围为整个函数内
let scope = "局部变量";
document.writeln(scope + "<br/>")
}
test();
输出结果:
JavaScript的变量提升机制,指的是变量声明总是会被解释器“提升”到函数体顶部
(变量提升只是提升变量声明的部分,并不会提升变量赋值部分)
同理下面代码:
var x=100;
var y=200;
function foo(){
document.writeln(x + "<br />");
document.writeln(y + "<br />");
if(false){
var x=1;
}
return;
var y=2;
}
foo();
按理说 x=1,与y=2不可能获得执行机会,而且定义了全局变量 x=100,y=200 ,但是由于变量提升机制输出结果为:
这就是只提升了函数的声明,并没有给它赋值,所以会显示undefined。
6. 输出浏览器的版本
alert("浏览器版本为:" + navigator.appVersion);
7. js的数组定义的三种方式
同一个数组中的数组元素可以有不同的数据类型
var a = [3 ,5 ,23];
var b = [];
var c = new Array();
b[0]='hello';
b[1]=6;
c[5]=true;
c[7]=null;
alert(a + "\n" + b +"\n" +c
+ "\na数组的长度:" + a.length
+ "\nb数组的长度:" + b.length
+ "\nc数组的长度:" + c.length);
8. js的数组也可以作为栈和队列使用
var stack = [];
//将数组当栈使用
//入栈
stack.push("孙悟空");
stack.push("猪八戒");
stack.push("白骨精");
//出栈
console.log(stack.pop());
console.log(stack.pop());
console.log(stack.pop());
//将数组当队列使用
var queue = [];
//入队列
queue.unshift("孙悟空");
queue.unshift("猪八戒");
queue.unshift("白骨精");
//出队列
console.log(queue.shift());
console.log(queue.shift());
console.log(queue.shift());
不难发现,栈和队列的输出结果竟然是一致的。
解释:
push方法是在尾部插入元素
pop是把数组尾部的元素弹出来
unshift是在头部插入元素
shift是把数组头部的元素弹出来
所以上面代码中的进出:
stack = ["孙悟空","猪八戒","白骨精"];
//pop弹出尾部元素
//所以顺序是:白骨精、猪八戒、孙悟空
queue = ["白骨精","猪八戒","孙悟空"];
//shift弹出头部元素
//所以顺序是:白骨精、猪八戒、孙悟空
以上,所以想实现真正的队列和栈需要两者灵活配合使用
9. 对 js 数组进行操作的函数
-
concat()为数组添加元素
-
reverse();反转数组
-
join()将多个元素用定界符拼接在一起
-
slice()截取数组
-
sort()排序
-
splice()截取追加
var a = ["html",2,"yeeku"];
var f = [4,5,6,7,8];
console.log(a.concat(4,5));
console.log(a.concat([4,5]));
console.log(a.concat(f,[6,7]));
console.log("-----------------------------------------")
var b = ["html",20,"is",99,"good"];
console.log(b.join());
console.log(b.join("+"));
console.log(b.join("冲冲冲"));
console.log("-----------------------------------------")
var c = ["html","css","jquery","bootstrap"];
c.reverse();
console.log(c);
console.log(c.sort());
console.log("-----------------------------------------")
var d = ["yeeku","leegang","crazyit","fkit","charlie"];
console.log(d.slice(3));
console.log(d.slice(2,4));
console.log(d.slice(1,-2));
console.log(d.slice(-3,-2));
console.log("-----------------------------------------")
var e = ["yeeku","leegang","crazyit","fkit","charlie"];
console.log(e.splice(3));
console.log(e.splice(1,1));
console.log(e.splice(0,1,20,30,40));
console.log(e);
注意:
对于sort函数
默认形式:c.sort();
默认升序排序
我们可以通过给参数,来调整升序还是降序
但是必须是函数
var c = [1,9,2,7,6,1,5,3];
c.sort(function(c,b){
return b-c;
});
console.log(c);
即如果数组中第一个大于第二个数,则降序,否则升序。
10. js的赋值运算符 "=" 是有值的,值等于等号右边的值,所以可以连续赋值
var a=b=c=d=e=f=7;
11. js抛出异常
try{
for (var i=0;i<10;i++){
document.writeln(i + '<br />');
if(i>4){
throw new Error('用户自定义异常')
}
}
}catch(e){
document.writeln('系统出现异常' + e.message + '<br />');
}finally{
document.writeln('系统的finally块');
}
12. for in 遍历
for(propName in navigator){
document.write('属性'+propName+'的值是:'+navigator[propName]);
document.write("<br />");
}
13. 用标签的形式,break 跳到对应的标签
outer:
for(var i = 0;i < 5; i++){
for(var j = 0;j < 5 ;j++){
document.writeln('j的值为:'+j);
if(j>=2)break outer;
document.writeln('i的值为:' + i);
document.writeln('<br />');
}
}
执行结果:
14. 函数提升
hello('zkm');
function hello(name){
alert('你好,'+name)
}
15. return 返回值 & typeof 方法
function hello(name){
if(typeof name == 'string'){
return name + ',你好!';
}
return '只能输入字符串!';
}
alert(hello('zkm'));
16. 匿名函数方式
var f = function(name){
document.writeln('匿名函数');
document.writeln('你好'+name);
};
f('zkm');
17. 函数、方法、对象、变量、类,在定义一个 JavaScript 函数时同时定义了这么多东西
比如输出不加 “()”的hello
var hello = function(name){
return name + ",你好!";
}
alert("hello是否为Function对象:" + (hello instanceof Function)
+ "\nhello是否为Object对象:" + (hello instanceof Object));
alert(hello);
执行结果:
加上 “()”的hello 即 hello();
var hello = function(name){
return name + ",你好!";
}
alert("hello是否为Function对象:" + (hello instanceof Function)
+ "\nhello是否为Object对象:" + (hello instanceof Object));
alert(hello());
执行结果:
18. 利用函数创建对象构造器
function Person(name,age){
this.name = name;
this.age = age;
this.info = function(){
document.writeln("我的名字是:" + this.name + "<br />");
document.writeln("我的年纪是:" + this.age + "<br />");
}
}
var p = new Person('zkm',29);
p.info();
执行结果:
19. 弹出到一个新的网页
with(window.open()){
document.writeln("这是一个弹出的新网页!");
}
执行结果:
20. 另一种方法定义一个对象,并定义一个对象内的方法
var p = {
walk:function(){
for(var i=0;i<5;i++){
document.writeln("慢慢走...");
}
}
}
p.walk();
21. 避免变量与函数重名
function hello(name){
document.writeln(name + ",你好! <br />");
}
hello('zkm');
alert(hello);
hello = "冲冲冲";
hello("孙悟空");
依次执行的结果:
最后会报错,hello = "冲冲冲"; 把 hello 又定义成了变量,会覆盖掉函数,所以 hello 不在是函数了,而是一个字符串变量。
变量提升与函数提升同时存在时,若变量赋值了,则变量先提升,否则函数提升。
22. 类属性与实例属性
function Person(national, age){
//this修饰的变量为实例属性
this.age = age;
//Person修饰的变量为类属性
Person.national = national;
//var修饰的变量为局部变量
var bb = 0;
}
var p1 = new Person('中国',29);
document.write("创建一个Person对象<br />");
document.writeln("p1的age属性为" + p1.age + "<br />");
document.writeln("p1的national属性为" + p1.national + "<br />");
document.writeln("通过Person访问静态national属性为" + Person.national + "<br />");
document.writeln("p1的bb属性为" + p1.bb + "<br /><hr />");
var p2 = new Person('美国',32);
document.writeln("创建两个对象之后<br />");
document.writeln("p1的age属性为" + p1.age + "<br />");
document.writeln("p1的national属性为" + p1.national + "<br />");
document.writeln("p2的age属性为" + p2.age + "<br />");
document.writeln("p2的national属性为" + p2.national + "<br />");
document.writeln("通过Person访问静态national属性为" + Person.national + "<br />");
执行结果:
23. 为对象增加属性
function Student(grade,subject){
this.grade = grade;
Student.subject = subject;
}
s1 = new Student(5,'Java');
with(document){
writeln('s1的grade属性:'+ s1.grade + "<br />");
writeln('s1的subject属性:'+ s1.subject + "<br />");
writeln('Student的subject属性:'+ Student.subject + "<br />");
}
//为s1对象的subject属性赋值,即为它增加一个subject属性
s1.subject = 'Ruby';
with(document){
writeln('s1的grade属性:'+ s1.grade + "<br />");
writeln('s1的subject属性:'+ s1.subject + "<br />");
writeln('Student的subject属性:'+ Student.subject + "<br />");
}
执行结果:
24. 函数的独立性
function Person(name){
this.name = name;
this.info = function(){
alert("我的name是:" +this.name);
}
}
var p = new Person("zkm");
p.info();
window.p.info();
//以window对象调用p的info属性
//下面这句话就相当于 p.info.call(window) = window.info()
//所以 name 就调用的是window下的name
p.info.call(window);
执行结果:
前两次:
最后一次:
但是当我们定义了 var name ="ccc";
前两次:
最后一次:
这是直接输出的window下的name
但是当我们删除了 var name ="ccc";
他还是会输出这个,清缓存也没用,把这些函数里的name换成另一个比如iname他就又正常了,我很不解!!!!
25. 再次验证函数的独立性
function Dog(name ,age ,bark){
this.name = name ;
this.age = age;
this.bark = bark;
this.info = function(){
return this.name + "的年龄为:" + this.age + "它的叫声:" + this.bark;
}
}
var dog = new Dog("旺财",3,"汪汪,汪汪,...");
function Cat(name,age){
this.name = name;
this.age = age;
}
var cat = new Cat("Kitty",2);
alert(dog.info.call(cat));
最后一句代码:通过 cat 这个对象,去调用dog的info方法
执行结果:
26. 给函数传参不完整
function Dog(name,age,brak){
this.name = name;
this.age = age;
this.brak = brak;
}
var dog = new Dog("ccc");
alert(dog.age)
执行结果:
undefined
27. 命名函数与匿名函数的提升规则
全局函数会被提升到 script 的顶端,而匿名函数只会提升被赋值的变量,而不会提升函数的定义
28. 变量与函数提升规则
变量如果赋值则,优先级大于函数,否则小于函数
而函数也要考虑是命名函数,还是匿名函数,命名函数按照规则没问题,而匿名函数需要特殊看待。
function a(){
}
var a;
console.log(a); //输出代码
var b;
function b(){
}
console.log(b); //输出代码
var c = 1;
function c(){
}
console.log(c); //输出1
function d(){
}
var d = 1;
console.log(d); //输出1