目录
2.为什么 typeof 对象和数组以及null 都是object类型
1.js的内置类型
number ,string , boolean , 数组,对象 ,null ,undefined ,symbol
2.为什么 typeof 对象和数组以及null 都是object类型
只设计了五种数据类型(对象、整数、浮点数、字符串和布尔值),完全没考虑null 。
typeof是底层用的二进制进行对比 object 的前三位是 000 ,null 机器数据是空 也是0 所以null 就是object 类型。
补充:
区分 (array , object ,null)
判断数组的方式
1.Array.isArray(arr)
2.Object.prototype.toString.call(arr)
3.arr instanceof Array
4.Object.getPrototypeOf(arr) === Array.prototype
5.arr.constructor == Array
区分null
1.null === null
3.let , const ,var 的区别
首先 const 和 let 都是 es6新增加的 let 是声明变量的
const 是声明常量的 在声明的时候必须初始化 一旦初始化,就不能重新赋值了
let num = 10 ; const name = "张三" //name ="李四" ; //报错
let不可以重复定义 ,var 可以
let num = 10 ; //let num = 10 ; //报错
let 没有变量提升 , 在let 上面定义的话会报错
console.log(num) //num is not defined let num = 10 ;
暂时性死区 在一个作用域中 只要定义了let ,const 就会只在这个区域找不会向上查找了
如果在let const 之前调用 则会报错
let age = 19; getAge() function getAge() { console.log(age);//报错 age is not difined let age = '哈哈哈'; }
var没有块级作用域,let和const有块级作用域
for (var i = 0; i <= 10; i++) {} console.log(i); //11 for (let i = 0; i <= 10; i++) {} console.log(i); //报错
4.
var obj = {
n:10,
m:obj.n
}
console.log(obj);
会报错//
1.第一种解释 (不知道对不对)
基本数据类型存栈,引用数据类型在堆里,堆里存的是obj的内容, 然后堆里是个新的内存空间吧 是先声明 然后再定义 然后在堆里查找 obj 的时候 堆的地址还没有形成 还没有赋值给obj 就是Undefined
2.第二种解释
用对象的说法,就是 当使用花括号字面量表示的时候,JS引擎后台会使用new Object()来进行包装,最后赋值给 obj ,而这个时候obj还没创建,所以无法访问。
5.
var test = (function(i){
return function(){
console.log(i * 2)
}
})(2)
test(5)
答案 :输出 4
6.什么是原型链
首先每个对象上都有一个__proto __属性 ,指向了父类的prototype。 当我们在一个对象上查找一个属性的时候 ,先去对象上去查找 ,找不到时去对象的__proto__ 也就是父类的prototype上去查找,直到找到Object.prototype上,找不到的话就返回为null ,这就是原型链
7.什么是promise
promise 是一种解决异步程序的方案 ,比之前传统的解决方法更合理更强大。
其实promise相当于一个容器,里面装着异步请求的结果。
promise有三种状态:pending(进行中) ,resolve(成功) ,reject(失败)。
状态一旦改变就不会再受外界影响,只有异步操作的结果可以决定当前是哪种状态。
状态一旦改变就不会再次改变 。状态只会从pending到resolve 或者从pending到reject ,只要状态一旦改变 ,做任何操作都不会再次改变。
在项目中promise虽然解决了传统的回调地狱的问题 ,但是也需要不断地.then()去形成一个回调链,这样的代码其实很不美观,所以我们一般在项目中都会使用async await ,使代码看起来像是同步的代码一样。
8.new 做了什么
class Person {
name:string,
getName(){
return this.name ;
}
}
let p1 = new Person();
- 首先创建一个新对象 var obj = {} ;
- 新对象继承构造函数的原型即 obj.__proto == Person.prototype
- 将Person对象的this指向新对象 ,相当于将属性和方法都加到新对象上去。Person.call(obj)
- 返回一个新对象 ,如果没有的话 返回this
9.什么是闭包
我的理解:
在一个函数内返回一个变量或者函数,导致这个变量或者函数不会因为函数的调用结束而销毁的函数叫做闭包。
闭包可以在外部访问函数内部的变量,我们的程序中会经常用到闭包,但是闭包的使用不当同样会导致内存泄漏,所以我们要将所调用的方法置为null。
别人的理解:
函数嵌套函数,且内部函数调用父级作用域的变量就可以称之为闭包
闭包的优点可以读取外层函数内部的变量。延长局部变量的生命周期,实现变量数据共享。
缺点是由于闭包执行完成之后会把外层函数中的变量保存到了内存中,消耗内存,以及数据泄漏,存在安全隐患所以不能滥用闭包否则影响性能。
最好的方法就是在退出函数之前,将不使用的局部变量全部删除,这样减少内存消耗,优化性能
闭包的应用场景:防抖,节流,计时器
10.关于this指向问题
this永远指向最后一个调用他的对象
- 在对象中定义的函数中的this指向调用的对象
let obj = { name:'zs', getName(){ return this.name; } } obj.getName() // zs
- 在普通函数中 、
匿名函数自调
、回调函数
中的this指向window(严格模式(use strict)下,this指向undefinedgetName(){ console.log(this) //window对象 } getName()
- 在构造方法中 this指向被创建的对象的实例
class people{ name ='zss' constructor(name){ console.log(this); //People{name:'zss'} this.name = name } } const p = new people('zs');
- 在事件调用中 this指向dom元素
let box = document.getElementById('box') box.onclick = function(){ console.log(this); //<div id="box"> </div> }
- 箭头函数没有this指向 ,永远指向他的父级的this指向
let obj = { name:'zs', age:18 , getName:()=>{ console.log(this); //window } } obj.getName();
- 其他的情况指向window或者undefined
改变this的指向
this 指向可以改变的使用apply ,call ,bind都可以改变this 的指向
// 箭头函数没有this,所以不能使用call、apply、bind来改变this的指向
// const getNameFn = ()=>{
// console.log(this); //window
// }
const getNameFn = function(){
console.log(this); //obj
}
getNameFn.apply(obj);
getNameFn.call(obj);
区别:
- apply:可以立即执行函数调用 ,接受两个参数 ,第一个参数是this的指向,第二个参数是数组,里面存放函数的参数
- call:立即执行函数的调用 ,可以接收多个参数,第一个参数是this的指向,后面的参数按顺序传给函数
- bind:创建了一个与原函数一样的函数,不会立即执行,需要手动调用 ,第一个也是this指向 ,改变了this是永久的不会再被改变 ,传入多个参数,传入的参数会被当成实参永久保存
const getNameFn = function(...ars){ console.log(ars); console.log(this); //obj } getNameFn.apply(obj,[19]); getNameFn.call(obj,18,19); const a = getNameFn.bind(obj ,10 ,20) ; a() const b =a.bind(Window ); b() //仍然指向obj 其中仍然存在 10 ,20
11.箭头函数与普通函数的区别
- 箭头函数没有this指向,箭头函数中的this是他的执行上下文的this指向 ,所以不能使用call、apply、bind来改变this的指向
- 箭头函数没有caller,arguments,prototype
- 箭头函数不能作为构造函数 ,不能使用new来调用
//普通函数 const Animal = function(name,age){ this.name = name ; this.age = age ; } //箭头函数 // const Animal = (name,age)=>{ // this.name = name ; // this.age = age ; // } const cat = new Animal('zs' ,18 ) console.log(cat);
- 箭头函数不能重复命名参数
function fn(name,name) { console.log('fn:',name) } var fn2 = (name,name) => { console.log('fn2',name) } fn('zs','ls') // 'ls' fn2('zs','ls') // 报错