JS由哪三部分组成?
ECMAScript:js核心内容,描述了语言的基础语法,比如var,for,数据类型(数组、字符串)
文档对象模型(DOM):DOM把整个HTML页面规划为元素构成的文档,
浏览器对象模型(BOM):对浏览器窗口进行访问和操作
JS有哪些内置对象?
String Boolean number array object function math date RegExp正则...
Math
abs() sqrt() max() min()
Data
new Data() getYear()
Array
String
concat()
concat() 方法用于连接两个或多个数组。
该方法不会改变现有的数组,而是返回一个新的数组。
length() slice()不会改变原有数组 split()
操作数组的方法有哪些?
push() pop() splice() unshift() shift() reverse() concat() join() map() filter()
every() some() reduce() isArray() findIndex()
哪些会改变原数组?
push() pop() unshift() shift() sort() reverse() splice()
JS对数据类的检测方式有哪些?
typeof()
instanceof()
constructor()
Object.prototype.toString.call()
// typeof() 对于基本数据类型没问题,遇到引用数据类型就不管用了
console.log( typeof 666) //number
console.log(typeof[1,2,3]) //object
// instanceof() 只能判断引用数据类型,不能判断基本数据类型
console.log([] instanceof Array) //true
console.log('abc' instanceof String) //false
// constructor() 几乎可以判断基本数据类型和引用数据类型;如果声明了一个构造函数,并把它的原型指向了Array
console.log(('abc').constructor === String) //true
// Object.prototype.toString.call() 完美解决方案
var opt = Object.prototype.toString
console.log(opt.call(2))
console.log(opt.call(true))
console.log(opt.call('aaa'))
console.log(opt.call([]))
console.log(opt.call({}))
说一下闭包,闭包有什么特点?
什么是闭包?函数嵌套函数,内部函数被外部函数返回并保存下来时,就会产生闭包
特点:可以重复利用变量,并且这个变量不会污染全局的一种机制;这个变量是一直保存在内存中,不会被垃圾回收机制回收。
缺点:闭包较多时候,会消耗内存,导致页面的性能下降,在IE浏览器中才会导致内存泄漏
使用场景:防抖、节流,函数嵌套避免全局污染的时候
function fn(a) {
return function(){
console.log(a)
}
}
var fo = fn(2)
fo()
前端内存泄漏怎么理解?
JS里已经分配内存地址的对象,但是由于长时间没有释放或者没办法清楚,造成长期占用内存的现象,会让内存资源大幅下降,最终导致运行速度慢,甚至崩溃的情况。
垃圾回收机制
因素:一些为生命周期赋值的变量,一些未清空的定时器,过度的闭包,一些引用元素没有被清除。
事件委托(事件代理)是什么?
又叫事件代理,原理就是利用了事件冒泡的机制来实现,也就是说把子元素的事件绑定到了父元素的身上,如果子元素阻止了事件冒泡,那么委托也就不成立。
阻止事件冒泡:event.stopPropagation()
addEventListener('click',函数名,true/false) 默认是false(事件冒泡),true(事件捕获)
好处:提高性能,减少了事件的绑定,也就减少了内存的占用。
基本数据类型和引用数据类型的区别?
基本数据类型 :String Number Boolean undefinded null
基本数据类型保存在栈内存当中,保存的就是一个具体的值。
引用数据类型(复杂数据类型)Object Function Array
保存在堆内存当中,声明一个引用类型的变量的时候,保存的是引用数据类型的地址
假如声明两个引用数据类型同时指向了一个地址的时候,修改其中一个那么另外一个也会改变
var obj = {
name:'张三',
age:18
}
var obj1 = obj
obj1.name = '李四'
console.log(obj)
console.log(obj1)
console.log(obj == obj1) //true
说一下原型链
原型就是一个普通对象,它是为构造函数的实例共享属性和方法:所有实例中引用的原型都是同一个对象
使用prototype方法可以把方法挂在原型上,内存只保存一份
__proto__可以理解为指针,实例对象中的属性,指向了构造函数的原型(prototype)
一个实例对象在调用属性和方法的时候,会依次从实例本身、构造函数原型、原型的原型上去查找
这样的查找线程像是一个链条
function Person(){
this.say = function(){
console.log('唱歌')
}
}
var p1 = new Person()
var p2 = new Person()
p1.say() // 唱歌
p2.say() // 唱歌
// 虽然打印出来的一样但是用了两个内存,为了解决这个问题js发明了原型,这样只要存一份即可,剩下所有的实例都可以共享它
function Person(){
this.say = function(){
console.log('唱歌')
}
}
Person.prototype.look = function(){
console.log('西游记')
}
var p1 = new Person()
var p2 = new Person()
p1.look() // 西游记
p2.look() // 西游记
function Person(){
}
Person.prototype.look = function(){
console.log('西游记')
}
var p1 = new Person()
var p2 = new Person()
console.log(p1.__proto__ ===Person.prototype) //true
new操作符具体做了什么?
先创建一个空对象
把空对象和构造函数通过原型链进行链接
把构造函数的this绑定到新的空对象身上
根据构造函数返回的类型判断,如果是值类型,则返回对象,如果是引用类型,就要返回这个引用类型
</