知识点
基本数据类型有哪些
ECMAScript 中有 5 中简单数据类型(也称为基本数据类型)Number
String
Boolean
Null
undefined
复杂数据类型有哪些
ECMAScript 中有 1 种复杂数据类型
-Object
本质上是由一组无序的名值对组成的。引用类型有哪些
Object
Array
Date
RegExp
Function
const
是什么
const
声明一个只读的常量。一旦声明,常量的值就不能改变。
const
声明的变量不得改变值,这意味着,const
一旦声明变量,就必须立即初始化,不能留到以后赋值。函数的意义
实现各种功能和业务逻辑,可重复使用,提高效率。
比较和区别
对象和数组区别
- 数组表示有序数据的集合,而对象表示无序数据的集合。
- 组的数据没有”名称”(name),对象的数据有”名称”(name)
var a = [1,2,3,4]; alert(a[2]) // 3 var a = {"城市":"北京", "面积":16800, "人口":1600}; alert(a['面积']); // 16800 alert(a.面积); // 16800
函数声明和变量函数声明有什么区别
函数声明、函数表达式、匿名函数
函数声明:function fnName () {…};使用function关键字声明一个函数,再指定一个函数名,叫函数声明。
函数表达式: var fnName = function () {…};使用function关键字声明一个函数,但未给函数命名,最后将匿名函数赋予一个变量,叫函数表达式,这是最常见的函数表达式语法形式。
匿名函数: function () {}; 使用function关键字声明一个函数,但未给函数命名,所以叫匿名函数,匿名函数属于函数表达式,匿名函数有很多作用,赋予一个变量则创建函数,赋予一个事件则成为事件处理程序或创建闭包等等。
函数声明和函数表达式不同之处在于:
Javascript引擎在解析javascript代码时会‘函数声明提升’(Function declaration Hoisting)当前执行环境(作用域)上的函数声明,‘提升’了函数声明,函数调用可在函数声明之前
而函数表达式必须等到Javascirtp引擎执行到它所在行时,才会从上而下一行一行地解析函数表达式,函数调用必须在函数表达式之后fnName(); function fnName(){ ... } //正常,因为‘提升’了函数声明,函数调用可在函数声明之前
fnName(); var fnName=function(){ ... } //报错,变量fnName还未保存对函数的引用,函数调用必须在函数表达式之后
getName();//2 var getName = function () { alert(1) }; function getName() { alert(2) };//函数声明提升到函数表达式之前。 getName();// 1
2.函数表达式后面可以加括号立即调用该函数,函数声明不可以,只能以fnName()形式调用 。
以下是两者差别的两个例子。var fnName=function(){ alert('Hello World'); }(); //函数表达式后面加括号,当javascript引擎解析到此处时能立即调用函数
function fnName(){ alert('Hello World'); }(); //不会报错,但是javascript引擎只解析函数声明,忽略后面的括号,函数声明不会被调用
function(){ console.log('Hello World'); }(); //语法错误,虽然匿名函数属于函数表达式,但是未进行赋值操作,
( function(){…} )()
和( function (){…} () )
这两种立即执行函数的写法
函数体后面加括号就能立即调用,则这个函数必须是函数表达式,不能是函数声明。函数声明在function前面加!、+、 -甚至是逗号等到都可以起到函数定义后立即执行的效果,而()、!、+、-、=等运算符,都将函数声明转换成函数表达式,消除了javascript引擎识别函数表达式和函数声明的歧义,告诉javascript引擎这是一个函数表达式,不是函数声明,可以在后面加括号,并立即执行函数的代码。例如:
(function(a){ console.log(a); //firebug输出123,使用()运算符 })(123); (function(a){ console.log(a); //firebug输出1234,使用()运算符 }(1234)); !function(a){ console.log(a); //firebug输出12345,使用!运算符 }(12345);
typeof
和instandof
区别- 它们都是用来判断一个变量是否为空,或者是什么类型的。
typeof
可以用来确定一个变量的数据类型,无论引用的是什么类型的对象,它都返回 “object”.instanceof
可以用来确定一个引用类型值的是什么类型的对象,无法判断基本数据类型(基本数据类型都返回false)
instanceof
常规用法:
第一、 判断一个实例是否属于某种引用类型类型var StringObject = new String("hello world"); console.log(StringObject instanceof String); // 输出 "true"
这段代码问的是“变量 StringObject 是否为 String 对象的实例?”
第二、在继承关系中用来判断一个实例是否属于它的父类型
// 判断 foo 是否是 Foo 类的实例 , 并且是否是其父类型的实例 function Aoo(){} function Foo(){} Foo.prototype = new Aoo();//JavaScript 原型继承 var foo = new Foo(); console.log(foo instanceof Foo)//true console.log(foo instanceof Aoo)//true
ES5 的
var
和 ES6 的let
变量声明的区别var xx; function test(){ var aa; //声明一 let bb;//声明二 this.cc;//声明三 //声明一局部代码块 { let dd;//声明四 } }
主要区别在于作用域不同。
let 声明的变量作用域为某个代码块。而代码块的长度可大可小。
也就是说,当按声明二的方式声明一个变量时,该变量的作用范围于为整个function语句。
当按声明四方式声明一个变量时,该变量的作用范围为局部的代码块。var 如果在函数内部,加var就是局部变量,不加是全局变量。
在函数外面,也就是说在window区域加不加var是一样的,该var变量的作用域为整个js文件周期(全局作用域)。this多用于函数内部,它永远指向调用他的那个对象
简单地说,用this声明的变量作用域也是全局的。
如果实例化test函数 var p=new test() 那么用p能访问test函数内的哪些变量呢?
答案是只有cc 。实际上this声明的变量是作用于上下文的。其他区别
1、ES5中使用var来声明变量,会产生作用域提升的问题。let相当于严格模式的var,不再存在提升变量的声明问题。例:var a=1; function scope(){ console.log(a); var a=2; } scope(); //得到的结果既不是1也不是2,是undefined 因为JS引擎会把变量的声明提升到当前作用域的最前面。 //即相当于 var a=1; function scope(){ var a; console.log(a); a=2; }
console.log( a ); //undefined 变量提升了。 var a=2; console.log(b); //b is not defined 不存在变量提升。 let b=2;
2、ES6里面新增的let,let声明过的变量不能在相同作用域内进行重复声明。
function variable(){ let a=0; var a=2; } variable(); //会报错,报'a' has already been declared的错,
3、let声明的变量只能在块级作用域内使用。
for(let i=0;i<3;i++){ console.log(i); //0,1,2 } console.log( i ); //报错:i is not defined
for(var i=0;i<3;i++){ console.log(i); //0,1,2 } console.log(i); //3 而在ES5里面使用var声明的变量在全局作用域之内都可以使用。
let声明的变量存在暂时性死区:
var tmp = 123; //存在全局变量tmp,但在下面let又声明了一个局部变量tmp, if (true) { tmp = 'abc'; // 所以在这里绑定的块级作用域在let声明前,因此报错ReferenceError:tmp is not defined let tmp;
DOMContentLoaded
、document.ready
、document.load
和window.onload
的区别
1.为什么要区分?我们需要给一些元素的事件绑定处理函数。但问题是,如果那个元素还没有加载到页面上,但是绑定事件已经执行完了,是没有效果的。
2.DOM文档加载流程:
(1) 解析HTML结构。
(2) 加载外部脚本和样式表文件。
(3) 解析并执行脚本代码。
(4) 构造HTML DOM模型。// DOMContentLoaded 相当于jQuery中的ready
(5) 加载图片等外部文件。
(6) 页面加载完毕。// load 和onload
DOMContentLoaded: DOM解析完成即触发此事件,不等待styles, images等资源的加载,DOMContentLoaded绑定到document
$(document).ready()
是 DOM结构绘制完毕后就执行,不必等到加载完毕,$(document).ready()
可以同时编写多个,并且都可以得到执行 ,$(document).ready(function(){})可以简写成$(function(){});
load & onload :页面所有元素加载完成后触发,有document load 和window.onload
(window.onload
不能同时编写多个,如果有多个window.onload方法,只会执行一个)原生JS写法:
// 不兼容老的浏览器,兼容写法见[jQuery中ready与load事件](http://www.imooc.com/code/3253),或用jQuery document.addEventListener("DOMContentLoaded", function() { // ...代码... }, false); window.addEventListener("load", function() { // ...代码... }, false); window.onload = function(){...};//只能一次性定义。 <body onload="func1();func1();">...</body>//嵌入html的写法
Jquery写法:
// DOMContentLoaded $(document).ready(function() { // ...代码... }); //load $(document).load(function() { // ...代码... }); $(window).load(function(){...});//jquery提供的load(),比onload方法灵活,可以多次定义并有先后次序。
函数赋值有括号和没括号的区别
function init() {
var name = "Mozilla"; // name 是一个被 init 创建的局部变量
function displayName() { // displayName() 是内部函数,一个闭包
console.log(name); // 使用了父函数中声明的变量
}
displayName();
return 190;
}//这是设计图
init();//Mozilla,按设计图做出一个成品送出去 ,返回值没人储存。
var a = init();//Mozilla,按设计图设计出一个成品,并把值赋值给a
a += init();//Mozilla,按设计图设计出一个成品,再把值赋值给a,a值是380
console.log(a)//380 , 设计出成品的价值 总价值
var b = init;//把设计图的使用权授权给b
b()//按设计图做出一个成品,返回值没人储存,执行完返回值丢失
console.log(b);//打印一张图纸
console.log(init);//打印一张图纸
console.log(b === init);// true b 跟 init是同一张图纸。
函数赋值加的括号时执行的意思,并且把返回值赋值给变量,如果没有赋值,返回值就没有储存而丢失。
没加括号就是把函数设计图的使用权给变量,这个变量跟函数名有同样的权力去创建新的对象和执行调用赋值等操作。