Javascript是什么?
JavaScript是一种属于网络的 脚本语言,被广泛应用于web应用开发
Javascript三大组成部分
- ECMAScripts: Javascript的核心,规定了语言标准。 描述了语言的基本语法(var、for、if、array等)和数据类型(Number、String、Boolean、Undefined、Object、Symbol)
- DOM:文档对象模型,使js用了操纵html标签的能力,(通过它,可以访问HTML文档的所有元素,例如获取、新增、删除DOM节点)(是 HTML 和 XML 的应用程序接口(API))
- BOM:浏览器对象模型,可以对浏览器窗口进行访问和操作。 (例如弹出新的浏览器窗口、移动、改变和管理浏览器窗口、获取网络浏览器信息(navigator object),页面信息(location object),用户屏幕分辨率的信息(screen object),对cookies的支持等等。)
数据类型
- 基本数据类型(基本类型):Number、String、Null、Undefined、Boolean、Symbol
- 复杂数据类型(引用类型):Object(Array,Date,RegExp,Function)
基本类型的数据是存放在栈内存中的,而引用类型的数据是存放在堆内存中的
基本类型的复制就是在栈内存开辟出了一个新的存储区域来存储新的变量,这个变量有他自己的值,只不过和前面的值一样,所以如果其中一个值的改变,则不会影响到另一个
引用类型的定义,是在栈内存中存储了一个指针,这个指针指向堆内存中该对象的存储地址,复制给另一个对象的过程其实是把对象的地址复制给了另一个对象变量,两个指针都指向一个对象,所以其中一个修改了,另外一个也会改变
简单介绍栈内存和堆内存?
待理解:https://www.jb51.net/article/223537.htm https://www.cnblogs.com/ljuyi/p/6100071.html
栈:
- 栈会自动分配内存空间,物理内存地址是连续的,存放基本类型,简单的数据段,占据固定大小的空间
- 在方法中定义的变量都是放在栈内存中。随着方法结束,这个方法的内存栈也自然销毁
- 优点:存取速度比堆快,仅次于直接位于CPU中的寄存器,数据可以共享
- 缺点:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性
堆:
- 堆是动态分配的内存。物理地址不连续,大小不定也不会自动释放,存放引用类型,实际上保存的不是变量本身,而是指向该对象的指针。
- 堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能呗另一个引用变量所引用(参数传递)
事件委托是什么?
利用事件冒泡的原理,让子元素所触发的事件,由父元素代替触发
Promise是什么?
Promise是一个对象,用来处理异步操作
特点: 对象的状态不受外界影响、一旦状态改变就不会再变
- 三个状态:pending、fulfilled、rejected
- 两个过程:pending→fulfilled(resolve)、pending→rejected(reject)
- 方法:then、catch
Promise构造函数接收一个函数作为参数,该函数的两个参数分别是resolve
和reject
,由JavaScript引擎提供
Promise 是异步编程的一种解决方案
全局变量
全局变量是在函数之外定义的变量。当前页面内有效。这些变量具有全局范围,在任何函数都可以使用它们,无需将它们作为参数传递给函数
局部变量
局部变量即定义在函数内部的变量。函数方法内有效。他的作用环境只局限在当前函数中
变量提升
在javascript中,变量声明都会被提升到函数的顶部。通俗的来说就是我们可以先使用变量再声明。
作用域
在作用域的范围中,我们可以使用这个作用域的变量进行各种操作。(负责收集和维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限)
作用域链
从当前作用域开始一层一层向上寻找某个变量,直到找到全局作用域,这种结构关系就叫做作用域链
什么是闭包? 闭包的作用? 闭包的影响?
定义:闭包就是能够读取其他函数内部变量的函数
作用:1:封装私有变量,使得函数不被GC回收(希望一个变量长期驻扎在内存当中(不被垃圾回收机制回收))(2)避免全局变量的污染
影响:如果过多使用闭包,容易导致内存泄漏
this是什么?
this就是一个指针,指向调用函数的对象
什么是变量提升?什么是暂时性死区
- 变量提升:变量声明之前就可以使用,值为undefined
- 暂时性死区:只要已进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量
(在代码块内,使用let、const声明变量之前,该变量都是不可用的,会抛出错误,这在语法上,称为“暂时性死区”)
原型、原型链
- 原型:实例化对象的实例的__proto__属性,该属性指向构造器函数的原型属性prototype
- 原型链:当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,就这样一直找下去。这种结构关系就是原型链
JavaScript的事件流模型都有什么?
- 事件冒泡:事件开始由具体的元素接收,然后逐级向上传播
- 事件捕捉:事件由最不具体的节点先接受,然后逐级向下,一直到最具体的
- DOM事件流:三个阶段:事件捕捉,目标阶段,事件冒泡
null和undefined的区别?
null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。
js延迟加载的方式有哪些?
defer和async、动态创建DOM方式(创建script,插入到DOM中,加载完毕后callBack)、按需异步载入js
解释什么是Json:
- JSON 是一种轻量级的数据交换格式。
- JSON 独立于语言和平台,JSON 解析器和 JSON 库支持许多不同的编程语言。
- JSON的语法表示三种类型值,简单值(字符串,数值,布尔值,null),数组,对象
new Array(arrayLength)
构造的数组是一个稀疏数组,里面是没有任何值的,只有长度。所以这个方式构造出来的数组是无法遍历的,也就无法用 map 遍历填充值了。
Array.apply
apply会把数组参数展开
伪数组和数组的区别?
伪数组例如NodeList、arguments,伪数组是一个Object,并不是真正的数组,它存在的意义就是让普通的对象也能正常使用数组的算法
可以使用Array.from转成真正的数组
forEach和map的区别?
两者都是接收三个参数:当前数组中元素、索引、当前数组
- forEach会修改原来的数组,不会返回执行结果,map是得到一个新的数组并返回
- forEach执行速度比map慢
- forEach适合不改变数据的情况,map适合需要改变数据的情况,因为更快,可以返回一个新数组,还可以复合使用其他语法
let arr = [1, 2, 3, 4, 5];
let arr2 = arr.map(value => value * value).filter(value => value > 10);
split()、 join()的区别?
前者将字符串分割成数组,后者将数据变为字符串
箭头函数和普通函数的区别?
- 箭头函数作为匿名函数,不能使用
new
关键字 - 箭头函数不绑定
this
,会捕获上下文this
,作为自己的this
值,任何方法都改变不了this
指向,(call(),bind(),apply()) - 箭头函数不绑定arguments,用rest参数替代
普通函数:可以使用arguments,也可以使用rest
function showArgs(...args){ console.log(args) } showArgs(1,2,3,4,5)
箭头函数:不绑定arguments,es6引入rest参数(形式为...变量名
)
let showArgs = (...args) => {
console.log(args)
}
showArgs(1,2,3,4,5)
call和apply的区别
- Object.call(this, arg1, arg2) 参数需要分开传
- Object.apply(this, [arg1, arg2]) 所有参数放在一个数组里面
get和post的区别
- post更安全(不会作为url的一部分,不会保存在服务器日志,以及浏览器浏览记录中)
- get会缓存静态资源,post不会(比如html页面、图片,谷歌火狐监测get请求的是静态资源,则会缓存,如果是数据,则不会缓存)
- post发送的数据更大,(get有url长度限制,不仅仅是参数值数据长度)
- post比get慢 (post在真正接收数据之前会先将请求头发送给服务器进行确认,然后才真正发送数据)
let、const、var的区别
- let和const声明的变量不会出现变量提升,var声明的变量会提升(let变量也会提升,只不过因为暂时死区的限制,不能在let声明变量之前使用)
- let和const是块级作用域,var是函数级作用域
- let和const不允许重复声明(会抛出错误)
- let和const声明变量之前使用,会抛出错误(暂时性死区)
- const声明一个只读的常量,一旦声明,不可以改变
exports, module.exports, export defaul 区别?
-
exports:导出的是模块函数本身,可以有多个
exports.func = function () {}
引入(需要加括号):
import {func} from './test'
-
module.exports:导出的是模块对象本身,当文件中出现多个,后面的module.exports会覆盖以前的
module.exports = { func: function () {} }
引入(可加可不加,不加就是引入模块对象本身):
import module from './test'
-
export default:只能有一个
export default function func() {console.log(1)}
引入(不用加括号):
import func from './test'
innerHTML和outerHTML的区别
innerHTML(元素内包含的内容)
outerHTML(自己以及元素内的内容)
offsetWidth offsetHeight和clientWidth clientHeight的区别
(1)offsetWidth (content宽度+padding宽度+border宽度)
(2)offsetHeight(content高度+padding高度+border高度)
(3)clientWidth(content宽度+padding宽度)
(4)clientHeight(content高度+padding高度)
http和https的区别?
- http标准端口是80,而https标准端口是443
- http无法加密,而https会对传输的数据进行加密
- http无需证书,而https需要CA机构wosign颁发的SSL证书
- http是不安全的,而https是安全的
cookie、localStorage、sessionStorage的区别?
共同点:都是保存在浏览器端,且同源的
不同点:
- cookie数据始终再同源的http请求中携带(即使不需要)
- cookie数据不能超过4k,sessionStorage和localStorage可以达到5M
- sessionStorage:仅在当前浏览器窗口关闭之前有效
- localStorage:始终有效,窗口或浏览器关闭也一直保存,可以用作持久数据
- cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
函数声明和函数表达式的区别?
-
函数声明
de() function de(){ return 1 }
-
函数表达式
//函数表达式 expression() error=> Cannot access 'expression' before initialization let expression = function(){ return 2 }
document load 和 document ready的区别?
- load:是在结构和样式,外部js以及图片加载完执行
- ready:是dom树创建完成就执行的方法,原生js没有这个方法,jquery$().ready(function(){})
== 和 ===的区别?
前者回自动转换类型,在判断
后者不会自动转换类型,直接去比较
判断类型
如果判断一个变量是不是数组?
- Array.isArray
- instanceof Array
- Object.prototype.toString.call
(借用Object的方法,Array,Function都是Object的实例,实例重写了原型的上toString方法,而不会调用Object原型上的方法,因此直接调用不能判断对象类型)
typeof返回哪些数据类型
function、string、boolean、number、undefined、object
instanceof的作用?
instanceof来检测某个对象是不是另一个对象的实例。(在js中判断一个变量的类型尝尝会用typeof运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回“object”。这就需要用到)
function Foo(){} var f1=new Foo(); console.log(f1 instanceof Foo);//true console.log(f1 instanceof Object);//true
new 的原理是什么?
- 创建一个空对象
- 继承了函数的原型,将对象的原型设置为函数的prototype对象。
- 属性和方法被加入到this引用得对象中,让函数的this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
- 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。
function new(func){ let target = {} targe.__proto = func.prototype let res = func.call(target) if(typeof(res) == 'object' || typeof(res) == 'function') { return res } } return target
数据sort原理
sort()方法的原理是调用toString()方法,得到数组项的字符串,然后再比较字符串的Unicode码的顺序进行排序,即使数组中的每一项都是数值,比较的也是字符串的顺序
Ajax原理
- 创建ajax对象:
var xhr = new XMLHttpRequest();
- 判断数据方式,打开请求:
xhr.open('GET', 'example.txt', true);
- 发送请求到服务器:
xhr.send();
-
数据接收完成,判断http响应状态:
xhr.onreadystatechange =function(){}
- (1)当readystate值从一个值变为另一个值时,都会触发readystatechange事件。
- (2)当readystate==4时,表示已经接收到全部响应数据。
- (3)当status ==200时,表示服务器成功返回页面和数据。
- (4)如果(2)和(3)内容同时满足,则可以通过xhr.responseText,获得服务器返回的内容。
// 第一步:创建一个异步对象 let xhr = new XMLHttpRequest(); // 第二步: 设置状态监听函数 xhr.onreadystatechange = function () { log(xhr.readyState); log(xhr.status); // 第五步:在监听函数中,判断readyState=4 && status=200表示请求成功 if (xhr.readyState == 4 && xhr.status == 200) { log(xhr.responseText) // 第六步: 使用responseText、responseXML接受响应数据,并使用原生JS操作DOM进行显示 showMessage(JSON.parse(xhr.responseText).msg); } else { log(xhr.responseText) } } // 第三步: open一个链接 xhr.open("post", "https://192.168.", false); //true异步请求, // false同步 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 第四步: send一个请求。 可以发送对象和字符串,不需要传递数据发送null xhr.send(data);
列举强制类型转换和隐式类型转换
- 强制:String()、Boolean()、Number()、parseInt()、parseFloat()
- 隐式:四则运算,==
列举操作数组的几种方法?
let arr = [1, 2, 3]
arr.push(1)
添加元素到数组的末尾arr.unshift(1)
添加元素到数组的开始arr.pop()
删除数组末尾的元素arr.shift()
删除数组头部的元素arr.splice(startIndex, endIndex)
截取数据指定范围的元素(会改变原始数组)arr.slice(startIndex, endIndex)
截取数据指定范围的元素(不会改变原始数组)arr.indexOf(1)
返回指定元素的下标,存在则返回对应下标,不存在则返回-1arr.includes(1)
判断元素是否存在,存在返回true,不存在返回falsearr.concat(arr2)
合并数组arr.reverse()
将数组中的元素位置颠倒,(数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。)
列举操作字符拆的几种方法?
string.charAt(index)
通过下标找对应的字符string.indexOf(value, startIndex)
通过字符去找对应的下标值(从左往右)string.lastIndexOf(value, startIndex)
通过字符去找对应的下标值(从右往左)
列举跨域通信的几种方式?
- jsonp
- 前端
<script> function addScriptTag(src){ var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function(){
addScriptTag("http://192.168.254.11111?callback=result"); } //回调函数 function result(data) { console.log(data); } </script>
-
- 例如node
ctx.body = `${callback({a:1})}`
- CORS(设置Access-Control-Allow-Origin:指定可访问资源的域名)
ctx.set('Access-Control-Allow-Origin', '*')
- postMessage(html5新增api用于多窗口消息),通过onmessage监听传递过来的数据
为什么 [] == false?
对象和布尔值进行比较时,对象先转换为字符串,然后再转换为数字,布尔值直接转换为数字
为什么NaN !== NaN?
这是隐式转换的一个很大的弊端,es6的includes方法可以检测出NaN等于NaN,这是一大进步
为什么null != 0?
这时候两边的类型也不同,但是却没有做类型转换,why?因为这时候二者都已经是基本数据类型了,没有办法在进行转换了,所以二者的类型都不可能相同,结果自然为false
为什么null == undefined?
这是一种规定
if x is null and y is undefined, return true if y is null and x is undefined, return true
为什么 !![] = true?
这里并没有涉及 == 比较,只需要判断 [] 是true还是false即可
为什么[] == ![]?
! 优先级是高于 == ,