2020前端面试题总结

JS垃圾回收机制

(1)标记清除

是javascript中最常用的垃圾回收方式。
当变量进入执行环境时,就标记这个变量为“进入环境”。
从逻辑上讲,永远不能释放进入环境的变量所占用的内存,
因为只要执行流进入相应的环境,就可能会用到他们。
当变量离开环境时,则将其标记为“离开环境”。

垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记。
然后,它会去掉环境中的变量以及被环境中的变量引用的标记。
而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。
最后。垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间。

(2)引用计数

另一种不太常见的垃圾回收策略是引用计数。
引用计数的含义是跟踪记录每个值被引用的次数。
当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是1。
相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数就减1。
当这个引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其所占的内存空间给收回来。
这样,垃圾收集器下次再运行时,它就会释放那些引用次数为0的值所占的内存。
JS哪些操作会造成内存泄露
JS中栈和堆详解
基本类型:String,Number,Boolean,Null,Undefined,这5种基本数据类型它们是直接按值存放的,所以可以直接访问。
引用类型:Function,Array,Object,当我们需要访问这三种引用类型的值时,首先得从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

栈(stack):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;
堆(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。

栈就像一个箱子,后放上去的,可以先出来
**1、缓存方式区别**
1.栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放;
2.堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

**2、堆栈数据结构区别**

堆(数据结构):堆可以被看成是一棵树,如:堆排序;

栈(数据结构):一种先进后出的数据结构。
AJAX请求过程
(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.

(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.

(3)设置响应HTTP请求状态变化的函数.

(4)发送HTTP请求.

(5)获取异步调用返回的数据.

(6)使用JavaScript和DOM实现局部刷新.
AJAX状态码

详见点此链接

栈和队列
队列是先进先出,有出口和入口,先进去可以先出来。

栈就像一个箱子,后放上去的,可以先出来
闭包

闭包一个函数中包含一个函数,能够访问其他函数内部变量的函数就叫闭包

function foo (){
    let name ='a'
    return function (){
        console.log(name)
    }
}
foo ()()///a


get/post区别
GET:一般用于信息获取,使用URL传递参数,对所发送信息的数量也有限制,一般在2000个字符

POST:一般用于修改服务器上的资源,对所发送的信息没有限制。

GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值,

也就是说Get是通过地址栏来传值,而Post是通过提交表单来传值。

然而,在以下情况中,请使用 POST 请求:

无法使用缓存文件(更新服务器上的文件或数据库)

向服务器发送大量数据(POST 没有数据量限制)

发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
localstorage、cookie,session
cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通 常经过加密),
cookie还可以设置有效时间 cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间 来回传递,
每次ajax请求都会吧cookie传送到后台,cookie一半用做用户登陆,后台可以根据 cookie信息判断用户是否登陆状态

sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。

区别在于 存储大小: cookie数据大小不能超过4k。
sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得 多,可以达到5M或更大。 
存储时间: localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据; 
sessionStorage 数据在当前浏览器窗口关闭后自动删除。 
cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭

链接

ES6常用语法 (新特性)
const ,let , promise, class , filter, forEach, call, bind, apply,解构赋值, 浅拷贝, 箭头函数, 
扩展运算符, 模板字符串, Array.from( ), new Set( )、symbol
Cookie的弊端
cookie

1.IE6或更低版本最多20个cookie
2.IE7和之后的版本最后可以有50个cookie。
3.Firefox最多50个cookie
4.chrome和Safari没有做硬性限制
Opera 会清理近期最少使用的Firefox会随机清理 4096字节,为了兼容性,一般不能超过 IE 提供了一种存储可以持久化用户数据,叫做IE5.0就开始支持。每个数据最多128K,每个域名下最多1M。这个持久化数据放在缓存中,如果缓存没有清理,那么会一直存在。

优点:极高的扩展性和可用性
1.通过良好的编程,控制保存在cookie中的session对象的大小。
2.通过加密和安全传输技术(SSL),减少cookie被破解的可能性。
3.只在cookie中存放不敏感数据,即使被盗也不会有重大损失。
4.控制cookie的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的cookie。
缺点:
1.`Cookie`数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉。

2.安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。

3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。


new一个对象过程发生了什么
  • 首先创建实例对象{ }
  • this变量引用该对象,同时还继承了构造函数的原型
  • 其次属性和方法被加入到this引用的对象中
  • 新创建的对象由this所引用,最后隐式返回this
function objectFactory() {

    var obj = new Object(),//从Object.prototype上克隆一个对象

    Constructor = [].shift.call(arguments);//取得外部传入的构造器

    var F=function(){};
    F.prototype= Constructor.prototype;
    obj=new F();//指向正确的原型

    var ret = Constructor.apply(obj, arguments);//借用外部传入的构造器给obj设置属性

    return typeof ret === 'object' ? ret : obj;//确保构造器总是返回一个对象

};
箭头函数与function函数的区别

原型链 【一句话解析什么是原型链】

遍历一个实列的属性时,先遍历实列对象上的属性,再遍历它的原型对象,一直遍历到Object
任何一个类(函数)都有原型对象,原型对象至少有两个属性(constructor,proto)。constructor指向函数本身,proto指向父类原型对象。

函数上有一个prototype属性,指向原型对象,通过它可以访问原型对象

函数的实列可以直接访问原型对象(因为实列上有proto指向构造函数的原型对象)

function Dog(){}        //类         
var obj=new Dog();      //实列
obj.name='沪江';
Dog.prototype.name="旺财";
Dog.prototype.eat=function(){
    console.log(this.name);
};
console.log(Dog.prototype.name);  //旺财
console.log(obj.prototype);      //undefined,prototype是类上才有的,实列上没有
obj.eat();                       //沪江(先遍历实列对象上的属性,再遍历它的原型对象)
原型继承

继承

Js如何实现继承?

构造函数绑定:使用 call 或 apply 方法,将父对象的构造函数绑定在子对象上

function Cat(name,color){
  Animal.apply(this, arguments);
  this.name = name;
  this.color = color;
}
实例继承:将子对象的 prototype 指向父对象的一个实例
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

拷贝继承:如果把父对象的所有属性和方法,拷贝进子对象
function extend(Child, Parent) {
   var p = Parent.prototype;
   var c = Child.prototype;
   for (var i in p) {
      c[i] = p[i];
   }
   c.uber = p;
}
原型继承:将子对象的 prototype 指向父对象的 prototype
function extend(Child, Parent) {
    var F = function(){};
     F.prototype = Parent.prototype;
     Child.prototype = new F();
     Child.prototype.constructor = Child;
     Child.uber = Parent.prototype;
}
ES6 语法糖 extends继承
class ColorPoint extends Point {
    constructor(x, y, color) {
        super(x, y); // 调用父类的constructor(x, y)
        this.color = color;
    }
    toString() {
        return this.color + ' ' + super.toString(); // 调用父类的toString()
    }
}}
变量的提升

const let var 的异同点

高阶函数

匿名函数和非匿名函数

简述事件流

简述vuex

promise

async、await

防抖

节流函数

进程和线程

for循环和forEach的区别

解释一下空元素的概念?

在HTML元素中,没有内容的 HTML 元素被称5261为空元4102素。

基本概述:
1,在用来描述网页的计算1653机语言中,有一种超文本标记语言,被称为HTML(Hyper Text Markup Language) 。而构成HTML内容的标记语言是由一套标记标签组成。这套标记标签通常被称为 HTML 标签 (HTML tag)。,
2,HTML 标签是由尖括号包围的关键词,比如 <html> ,通常是成对出现的,比如 <b> 和 </b>。
3,这些成对出现的HTML 标签,第一个标签是开始标签,第二个标签是结束标签。大多数HTML 标签在开始标签和结束标签之间都具有内容,而某些标签则没有内容。,
4,HTML中,从开始标签(start tag)到结束标签(end tag)的所有代码,被称为HTML元素。
5,由于HTML元素的内容是开始标签与结束标签之间的内容。而某些 HTML 元素具有空内容。(empty content),那些含有空内容的HTML元素,就是空元素。空元素是在开始标签中关闭的。
举例说明:

1,<br> 就是没有关闭标签的空元素(<br> 标签定义换行)。,
2,在 XHTML、XML 以及未来版本的 HTML 中,所有元素都必须被关闭。
3,在开始标签中添加斜杠,比如 <br />,是关闭空元素的正确方法,HTML、XHTML 和 XML 都接受这种方式。,
4,即使 <br> 在所有浏览器中都是有效的,但使用 <br /> 其实是更长远的保障。
DOCTYPE标签声明的文档类型包括?

HTML4支持三种DOCTYPE声明,而HTML5只支持一种,即: HTML4支持的三种DOCTYPE声明分别是严格型(strict)、过渡型(transitional)和框架型(Frameset)。

<!DOCTYPE HTML>
HTML5
求1-100和
function add (a,b){
    let num =a+b
    if(b+1>100){return num}
    else{return add(num,b+1)}
}
null和undefined的区别
null 代表空(转为数字的时候为0)

undefined代表未定义(转为数字的时候为NAN)

函数无return时返回undefined

null是JavaScript中的一个关键字他是一个程序级的

undefined!==null
什么是协议?
信号的传输总要基于一定的规则,这个规则就是协议

协议很多,http https ws DNS FTP SMTP

什么是http协议

http定义(超文本传输协议)
http特点
  • 一定是浏览器主动向服务器发起请求

  • 一次请求都会对应一次响应

  • 服务器响应时间不一定是即时的,但它一定会响应

    http状态码

  三个数字组成 第一个数字是响应的类别,分五种类别

  1XX: 我已经收到你的消息了,我正在处理 

  2XX: 表示我们的请求已经被成功接收,接受 

  3XX: 重定向 

  4XX: 客户端错误--请求语法或者请求无法实现 

  5XX: 服务器端错误

http工作原理(你能描述一下http工作原理吗)

    首先客户端连接服务器
    发送http请求
    服务器接收请求并返回http响应
    客户端解析HTML内容
http通信

B-S想要通信

1.确定基于什么协议(http)
2.表明请求方式(协商数据发送的方式)
3.建立连接(进行三次握手)
4.开始通信
5.断开连接(进行四次挥手)
什么是BS架构
浏览器/服务器模式

优点 分布性强 易维护
服务端发起请求的方式
1.使用axios发起请求
2.使用superagent 发起请求
3.使用http.get发起请求
4.使用http.request发起请求
5.远程拉取一个html页面到本地

链接

请求方式

GET / POST / PUT / DELETE

区别 (一个数据包还是两个数据包,传参方式不同)

浏览器对地址栏长度的限制

    IE浏览器对URL的长度现限制为2048字节。
    2.360极速浏览器对URL的长度限制为2118字节。
    3.Firefox(Browser)对URL的长度限制为65536字节。
    4.Safari(Browser)对URL的长度限制为80000字节。
    5.Opera(Browser)对URL的长度限制为190000字节。
同源策略

什么是源?

js如果两个页面(接口) 的协议,域名,端口号都相同 我们就认为它们具有相同的 源

什么是同源策略?

同源策略就是浏览器的一个安全限制,它阻止不相同的【域】之间进行数据交互

安全限制具体限制了哪些东西不可以被访问?(非同源限制)

无法读取非同源下的cookie localstorage 
无法接触非同源的dom
无法向非同源的地址发送 ajax请求

想要进行数据交互怎么办?
    
    跨【域】
怎么跨域?
1. jsonp方式 (利用js访问不受同源策略限制特性)
2. 跨域资源共享 ( S端 cors )
3. 设置反向代理 ( B端 )
https

三次握手 ,四次挥手

JS数据类型

基本数据类型:undefined、null、boolean、number、string、symbol(es6的新数据类型)
引用数据类型:object、array、function(统称为object)
typeof对于基本数据类型来说,除了 null都可以显示正确的类型,typeof对于对象来说,除了函数都会显示 objec

数据类型检测
typeof 5 // 'number'
typeof '5' // 'string'
typeof undefined // 'undefined'
typeof false// 'boolean'
typeof Symbol() // 'symbol'
console.log(typeof null)  //object
console.log(typeof NaN)   //number

typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'
this指向

普通函数

  • this 总是指向函数的直接调用者
  • 如果有 new 关键字,this 指向 new 出来的实例对象
  • 在事件中,this 指向触发这个事件的对象
  • IE 下 attachEvent 中的 this 总是指向全局对象 Window
    箭头函数中,函数体内的this对象,就是定义时所在作用域的对象,而不是使用时所在的作用域的对象。
function foo() {
  console.log(this.a)
}
var a = 1
foo()           //1       const obj = {
  a: 2,
  foo: foo
}
obj.foo()      //2const c = new foo()   //undefined
  • 对于直接调用 foo 来说,不管 foo 函数被放在了什么地方,this 一定是window
  • 对于 obj.foo() 来说,我们只需要记住,谁调用了函数,谁就是 this,所以在这个场景下 foo 函数中的 this 就是 obj 对象
  • 对于 new 的方式来说,this 被永远绑定在了 new出来的对象上,不会被任何方式改变 this
    说完了以上几种情况,其实很多代码中的 this 应该就没什么问题了,下面让我们看看箭头函数中的 this
function a() {
  return () => {
    return () => {
      console.log(this)
    }
  }
}
a()()()        //Window
  • 首先箭头函数其实是没有 this 的,箭头函数中的 this 只取决包裹箭头函数的第一个普通函数的 this。在这个例子中,因为包裹箭头函数的第一个普通函数是 a,所以此时的 this 是 window。另外对箭头函数使用 bind这类函数是无效的。
改变函数内部指向

callapplybind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向。
apply 、 call 、bind三者第一个参数都是 this 要指向的对象,也就是想指定的上下文;
apply 、 call 、bind三者都可以利用后续参数传参;
bind 是返回对应 函数,便于稍后调用;apply 、call 则是立即调用 。

function fruits() {}

fruits.prototype = {
	color: 'red',
	say: function() {
		console.log(this.color);
	}
};

var apple = new fruits();

apple.say();   // red, 此时方法里面的this 指的是fruits

banana = {color: 'yellow'};
apple.say.call(banana); //yellow,此时的this的指向已经通过call()方法改变了,指向的是banana,this.color就是banana.color='yellow';

apple.say.apply(banana);//yellow,同理,此时的this的指向已经通过apply()方法改变了,指向的是banana,this.color就是banana.color ='yellow';

apple.say.apply(null); //undefined, null是window下的,此时,this 就指向了window ,但是window下并没有clolr这个属性,因此this.clolr就是window.color=undefined;

call 传入参数列表
apply 传入数组

var array1 = [12,'foo'];
var array2 = ['Doe',100];

Array.prototype.push.call(array1, 'Doe',100)
Array.prototype.push.apply(array1, array2)

bind() 方法会创建一个 新函数,当调用这个新函数时,新函数会以创建它时传入 bind() 方法的第一个参数 作为 this,传入 bind() 方法的 第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。

var bar = function(){
	console.log(this.x);
};
var foo = {
	x:3
};
bar();    // undefined
var func = bar.bind(foo); 

func(); // 3
函数声明、函数表达式

链接

函数柯理化

把一个接收多个参数的函数改变成接收一个单一参数的函数,内部返回为一个可以接收余下参数的函数。柯理化函数一定是高阶函数。

//实现一个加法计算
function add(a,b){
  	return a+b
}
add(1,2)

//柯理化函数
function add(a){
  return (b)=>{
    	return a+b
  }
}
add(1)(2)
事件冒泡

JS执行机制,简述同步和异步的区别

宏任务、微任务

工厂模式,构造函数

在JavaScript中实现继承的方法

1,原型链继承

function SuperType(){
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.Fun = function(){
 
};
function SubType(){
}
//继承了SuperType
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green,black"
// 优点:简单 缺点 1.属性被实例共享 2.不能向父类传递参数

2,借用构造函数继承(经典继承)

function SuperType(){
    this.colors = ["red", "blue", "green"];
}
function SubType(){
    //继承了SuperType
    SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green"
 
 
function SuperType(name){
    this.name = name;
}
function SubType(){
    //继承了SuperType,同时还传递了参数
    SuperType.call(this, "Nicholas");
    //实例属性
    this.age = 29;
}
var instance = new SubType();
alert(instance.name); //"Nicholas";
alert(instance.age); //29
// 优点 1.避免了共享 2.可以向父类传参  缺点:方法在构造函数中定义,创建实例都会创建一遍方法

3,组合继承(原型+借用构造)

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};
function SubType(name, age){
    SuperType.call(this, name);//借用构造函数继承属性,二次调用
    this.age = age;
}
SubType.prototype = new SuperType();//借用原型链继承方法,一次调用
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27
// 缺点调用了两次父函数

4,原型式继承

function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}
//优点:简单 缺点:属性被实例共享

5,寄生式继承

function createAnother(original){
    var clone = object(original); //通过调用函数创建一个新对象
    clone.sayHi = function(){ //以某种方式来增强这个对象
        alert("hi");
    };
    return clone; //返回这个对象
}
var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"
//缺点:方法在构造函数中定义,创建实例都会创建一遍方法

6,寄生组合式继承

function inheritPrototype(subType, superType){
    var prototype = Object(superType.prototype); //创建对象
    prototype.constructor = subType; //增强对象
    subType.prototype = prototype; //指定对象
}
function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};
function SubType(name, age){
    SuperType.call(this, name);
    this.age = age;
}
inheritPrototype(SubType, SuperType);//实现继承
SubType.prototype.sayAge = function(){
    alert(this.age);
};
//优点 1 效率高,只调用一次父构造函数 2 原型链不变
事件冒泡

页面加载留白

二进制

什么是进制?

  • 世界上其实是有无数种进制的。

  • 运算规则布不变,实际结果也不变,不同进制表述结果的方式是不相同的。

有哪些进制?

*二进制*`
  一种以2为基数的计数法,采用0,1两个数字,逢二进1。

`八进制`
一种以8为基数的计数法,采用0,1,2,3,4,5,6,7八个数字,逢八进1。

`十进制`
一种以10为基数的计数法,采用0,1,2,3,4,5,6,7,8,9十个数字,逢十进1。

`十六进制`
一种以16为基数的计数法,采用0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f十六个数字和字符,逢十六进1。

进制

Buffer

什么是Buffer?

  • buffer是一个单独的内存区域。

  • Buffer是一个类。

  • 提供了很多操作字节的方法。

  • Buffer不需要引入。

    链接

什么是webSocket

什么是ws?

  • 双工通信
  • http不适合实时性的应用
  • ws可以实现即时通信,建立连接的主动方仍然是浏览器,双方都可以主动断开连接
  • ws不涉及跨域

ws协议区别于http最大的特点

服务端可以主动向客户端发送消息

链接

MVVM,MVC

MVVM

Model : 负责数据存储()

View : 负责页面展示,UI组件 将数据模型转化成 UI 展现出来 

View Model : 负责业务逻辑处理 (Ajax请求)对数据进行加工后交给视图展示 数据驱动视图,DOM操作被封装

MVVM 架构下 、View与Model之间没有直接联系,而是通过ViewModel进行交互 Model与ViewModel之间的交互是双向的,因此View的数据变化会同步到Model上,Model和ViewModel

之间的交互是双向的,因此View的数据变化会同步到Model中,Model的数据变化也会立即反映到View上

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而 View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作 DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理

MVC

Model : 接收View的注册,当自身数据变化时,执行view的刷新函数(主要实现逻辑)

View : 负责页面展示,放置视图相关的代码,以及一些刷新逻辑(原则上里面不应该有任何业务逻辑)

Controller : 控制器能够控制视图的变化,也能控制数据的变化,放置视图与模型上之间的映射
(原则上这里应该很薄,只是放一些事件绑定相关的代码,完成router,不实现真正的功能(函数体),只作为桥梁)

单项通信。一般情况下:View发送命令给控制器,控制器处理业务逻辑后控制Model,Model再去改View 
MVVM,MVC区别:
mvc 和 mvvm 其实区别并不大。都是一种设计思想。
主要就是 mvc 中 Controller 演变成 mvvm 中的 viewModel。
mvvm 主要解决了 mvc 中大量的 DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
和当 Model 频繁发生变化,开发者需要主动更新到 View 

深拷贝浅拷贝

引用类型无区别
复杂类型

全局提示(队列思想)


  let obj = {
    name: '',
    age: '',
    sex: ""
  }
  function isTypeNull(obj) {
    let str = Object.keys(obj).filter(item => obj[item] === '')
    if (str.length > 0) {
      alert(str[0] + '不可为空')
      return false
    }
    return true
  }
  console.log(isTypeNull(obj))
  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值