JavaScript基础知识题

①ES6新特性?学习地址 学习地址2

ECMAScript 6(ES6) 目前基本成为业界标准,它的普及速度比 ES5 要快很多,主要原因是现代浏览器对 ES6 的支持相当迅速,尤其是 Chrome 和 Firefox 浏览器,已经支持 ES6 中绝大多数的特性。

1.不一样的变量声明:const和let

ES6推荐使用let声明局部变量,相比之前的var(无论声明在何处,都会被视为声明在函数的最顶部)

let表示声明变量,而const表示声明常量,两者都为块级作用域;const 声明的变量都会被认为是常量,意思就是它的值被设置完成后就不能再修改了。

如果const的是一个对象,对象所包含的值是可以被修改的。抽象一点儿说,就是对象所指向的地址没有变就行。

有几个点需要注意:

  • let 关键词声明的变量不具备变量提升(hoisting)特性
  • let 和 const 声明只在最靠近的一个块中(花括号内)有效
  • 当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING
  • const 在声明时必须被赋值

2.模板字符串

在ES6之前,我们往往这么处理模板字符串:
通过“\”和“+”来构建模板

而对ES6来说

①基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定;

②ES6反引号(``)直接搞定;

3.箭头函数(Arrow Functions)

ES6 中,箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个 =>,紧接着是函数体;

箭头函数最直观的三个特点。

  • 不需要 function 关键字来创建函数
  • 省略 return 关键字
  • 继承当前上下文的 this 关键字
细节:当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略{} 和 return;  

4. 函数的参数默认值

在ES6之前,我们往往这样定义参数的默认值:

// ES6之前,当未传入参数时,text = 'default';
function printText(text) {
    text = text || 'default';
    console.log(text);
}

// ES6;
function printText(text = 'default') {
    console.log(text);
}

printText('hello'); // hello
printText();// default

5.Spread / Rest 操作符 

Spread / Rest 操作符指的是 ...,具体是 Spread 还是 Rest 需要看上下文语境。

当被用于迭代器中时,它是一个 Spread 操作符:

function foo(x,y,z) {
  console.log(x,y,z);
}
 
let arr = [1,2,3];
foo(...arr); // 1 2 3

当被用于函数传参时,是一个 Rest 操作符:当被用于函数传参时,是一个 Rest 操作符:

function foo(...args) {
  console.log(args);
}
foo( 1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]

6.二进制和八进制字面量

ES6 支持二进制和八进制的字面量,通过在数字前面添加 0o 或者0O 即可将其转换为八进制值:

let oValue = 0o10;
console.log(oValue); // 8
 
let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`
console.log(bValue); // 2

7.对象和数组解构

// 对象
const student = {
    name: 'Sam',
    age: 22,
    sex: '男'
}
// 数组
// const student = ['Sam', 22, '男'];

// ES5;
const name = student.name;
const age = student.age;
const sex = student.sex;
console.log(name + ' --- ' + age + ' --- ' + sex);

// ES6
const { name, age, sex } = student;
console.log(name + ' --- ' + age + ' --- ' + sex);

8.对象超类

ES6 允许在对象中使用 super 方法:

var parent = {
  foo() {
    console.log("Hello from the Parent");
  }
}
 
var child = {
  foo() {
    super.foo();
    console.log("Hello from the Child");
  }
}
 
Object.setPrototypeOf(child, parent);
child.foo(); // Hello from the Parent
             // Hello from the Child

9.for...of 和 for...in

for...of 用于遍历一个迭代器,如数组:

let letters = ['a', 'b', 'c'];
letters.size = 3;
for (let letter of letters) {
  console.log(letter);
}
// 结果: a, b, c

for...in 用来遍历对象中的属性:

 let stus = ["Sam", "22", "男"];
 for (let stu in stus) {
   console.log(stus[stu]);
  }
// 结果: Sam, 22, 男

10.ES6中的类

ES6 中支持 class 语法,不过,ES6的class不是新的对象继承模型,它只是原型链的语法糖表现形式。

函数中使用 static 关键词定义构造函数的的方法和属性:

class Student {
  constructor() {
    console.log("I'm a student.");
  }
 
  study() {
    console.log('study!');
  }
 
  static read() {
    console.log("Reading Now.");
  }
}
 
console.log(typeof Student); // function
let stu = new Student(); // "I'm a student."
stu.study(); // "study!"
stu.read(); // "Reading Now."

类中的继承和超集:

class Phone {
  constructor() {
    console.log("I'm a phone.");
  }
}
 
class MI extends Phone {
  constructor() {
    super();
    console.log("I'm a phone designed by xiaomi");
  }
}
 
let mi8 = new MI();

extends 允许一个子类继承父类,需要注意的是,子类的constructor 函数中需要执行 super() 函数。

当然,你也可以在子类方法中调用父类的方法,如super.parentMethodName()。
在 这里 阅读更多关于类的介绍。

有几点值得注意的是:

  • 类的声明不会提升(hoisting),如果你要使用某个 Class,那你必须在使用之前定义它,否则会抛出一个 ReferenceError 的错误
  • 在类中定义函数不需要使用 function 关键词
 

②简述JavaScript中的作用域链?学习地址

由于js存在全局变量和局部变量,在调用一个变量是,会对他的作用域链进行查找,如果函数内部定义了这个变量,那么取该变量的值,如果没有,那么向上一层查找,如果找到了,就获取这个值,如果还没找到,继续往上层查找,直到找到位置,如果找到最后也没找到,那么该变量的值为undefined。

 关于变量作用域的知识,相信学习JavaScript的朋友们一定早已经接触过,这里简单列举:  

  • JavaScript中变量是以对象属性的形式存在的:全局变量是全局对象的属性;局部变量是声明上下文对象的属性。(声明上下文对象是一个对用户不可见的内部实现,无法被引用,每当函数调用便创建这个对象以存放局部变量)
  • JavaScript虽然是解释型语言,但也存在预处理过程,其中便包含了声明提前。JavaScript解释器运行前,会先将整个程序中的变量声明(包括函数)提前到作用域顶部执行。所以在程序中变量的使用语句可以出现在声明语句之前。
  • JavaScript中没有块级作用域(像C语言那样用方括号{}划分作用域),而是使用函数作用域;
  • 不在任何函数体内声明的变量为全局变量,拥有全局作用域,可以在程序的任何位置被访问;而在函数内声明的变量(包括函数的参数)为局部变量,拥有局部作用域,只在函数内部有定义;
  • 若局部变量与全局变量重名,局部变量优先级高,可以遮盖全局变量;
  • 局部作用域可以相互嵌套(因为函数可以嵌套)

而作用域链的概念,接触过的人就没那么多了。其实作用域链很好理解,上方第一条已经明确了,JavaScript中变量是以对象属性的形式存在的,而作用域链其实就是这些对象组成的一个链表。全局变量是全局对象的属性,局部变量是声明上下文对象的属性。这些对象按从内向外的顺序链接,链尾当然就是全局对象。当函数运行中需要查找某一个变量的时候,就会沿着作用域链依次查询每个对象是否拥有与该变量同名的属性,如果存在则直接使用;若整条链上都不存在这个属性,便抛出ReferenceError。 在函数定义的时候,便创建了作用域链,链上的对象顺序便确定下来,当函数被调用,创建相应的对象添加到作用域链中,作用域链会随着函数的定义调用而更新。在嵌套函数中更是如此,每次调用外部函数时,内部函数又会重新定义,随之带来的就是作用域链的相应变化。关于作用域链的数量,可以用树来比喻,全局对象是根节点,函数的嵌套代表着树节点的层级关系,那么一个程序中作用域链的数量等于对应树中叶子节点的数量。 

 

③简述JS中创建自定义对象的方式?学习地址

自定义对象,指由用户创建的对象,兼容性问题要由编写者考虑。

1.对象直接量

var obj = {
  webName: "蚂蚁部落",
  address: "青岛市南区"
}

对象直接量是由键值对列表组成,列表包含在大括号中,属性名称和属性值由冒号分隔,每一个键值对之间是用逗号分隔,属性值可以是任何类型。

2.工厂模式

工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程。考虑到在ECMAScript种无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节,如下面例子所示:

function createPerson(name,age,job){
var o=new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayName=function(){
alert(this.name);
};
return o;

}
var person1=new createPerson("Nicholas",29,"Software Engineer");
var person2=new createPerson("Greg",27,"Doctor");

函数createPerson()能够根据接受的参数来构建一个包含所有必要信息的Person对象。可以无数次地调用这个函数,而每次它都会返回一个包含三个属性一个方法的对象。工厂模式虽然解决了创建多个类似对象的问题,但是却没有解决对象识别的问题。随之来的就是构造函数模式。

3.构造函数模式 new object() 

var obj = new object();

obj.webName = "蚂蚁部落"; 

obj.address = "青岛市南区"; 

以上代码采用构造函数方式创建对象obj,为其添加两个属性并赋值。

4.原型模式

在js中可以像“后端”一样使用原型模式创建对象。在调式的过程中,发现原型模式的确可以创建对象,而且相当于引用类型,也就是说,比如通过它来创建两个对象,那么这两个对象创建完后,若其中一个对象改变了原型模式中的属性的值,那么另一个对象也会受到影响,这也就是说不管创建多少个对象,那么这些对象都指向同一个存储空间,这也就是原型模式的一个优势,避免了资源的浪费,因为所有通过它创建的对象,都指向同一个内存空间。

5.组合使用构造函数模式和原型模式

 

④this关键字的作用是什么?学习地址

笼统的说,关键字this指向当前对象。比如,

顶级代码中的this指向全局对象;

在指定元素事件的时候,this指定当前发生事件的元素对象;

对于嵌套函数,如果嵌套函数作为方法被调用,其this指向调用它的对象;

如果作为函数调用,this是全局对象或者为undefined(严格模式下)。

 

⑤简要描述JS中的匿名函数?学习地址

匿名函数常用于定义不需要重复使用的函数,用完即释放。

用小括号括上,并在后面加一组小括号用来自调。

匿名函数的基本形式为(function(){...})();

前面的括号包含函数体,后面的括号就是给匿名函数传递参数并立即执行之。

匿名函数的作用是避免全局变量的污染以及函数名的冲突。

 

⑥什么是正则表达式?JS中如何应用?

正则表达式本身就是一个字符串,由一些普通字符和特殊字符组成,用以描述一种特定的字符规则的表达式。

正则表达式常用于在一段文本中搜索、匹配或替换特定形式的文本。

应用分为两种方式:

1.结合String对象的replace、search和match方法,实现对字符串的替换查找和匹配。

2.定义正则表达式对象,实现对字符串的复杂匹配操作。

 

⑦简述JS中定义函数的几种方式?学习地址

1.函数语句:即使用function关键字显式定义函数。

   function f(x){

        return x+1; 

   }

2.函数定义表达式,也称为"函数直接量"。

   var f = function(x){return x+1;} 

3.使用Function()构造函数定义。(必须大写F)

PS:如果一个函数是需要经常使用的函数就应该避免使用Function()构造函数来定义函数。Fuction()构造函数可以动态定义和编译函数,而function语句只能预编译函

数,因此在每次调用使用Function()构造函数定义的函数时,javascript都要编译一次函数。学习地址

 

⑧简述arguments对象的作用?

arguments可以访问函数的参数。即开发者在定义函数时,无需明确的为方法声明参数,也可以在方法体中使用arguments来访问参数。

这是因为arguments是一种特殊的对象,在函数代码中,表示函数的参数数组。

因此,可以通过使用arguments.length检测函数的参数个数,

可以通过下标arguments[index]来访问某个参数。

这样,可以用arguments对象判断传递给函数的参数个数并获取参数。适用于函数参数无法确定个数的情况。

 

⑨什么是逻辑短路?

逻辑短路是对于逻辑运算而言,是指,仅计算逻辑表达式的一部分便能确定结果,而不是对整个表达式计算的现象。

对于"&&"运算符,当第一个操作数为false时,将不会判断第二个操作数,因为结果一定是false。

对于"||"运算符,当第一个操作数为true时,将不会判断第二个操作数,因为结果一定是true。

 

⑩解释一下JS中局部变量和全局变量的区别?

全局变量拥有全局作用域,在JavaScript代码的任何地方都能访问;在函数内声明的变量只在函数体内有定义,即为局部变量,其作用域是局部性的。

需要注意的是,在函数体内声明局部变量时,如果不用var关键字,则将声明全局变量。

 

⑪简述JS的数据类型?

可分为基本类型和引用类型。

五大基本类型:string 、number 、boolean 、以及两个原始值: null(空) 和 undefined(未定义)

        基本类型的访问是按值访问的,就是说你可以操作保存在变量中的实际的值。有如下特点:

  1. 基本数据类型的值是不可变的(我们不能给基本数据类型添加属性和方法);
  2. 基本数据类型的比较是值的比较(只有他们的值相等的时候才是相等的);
  3. 基本数据类型的变量是存放在栈里面的  

引用类型(对象类型): Array 、Date 、Object 、RegExp 、Function

        对象是属性和方法的集合,也就是说引用数据类型可以拥有属性和方法,属性又可以包括基本数据类型和引用数据类型。有如下特点:
  1. 引用数据类型可以拥有属性和方法,且值是可变的;
  2. 引用数据类型的值是同时保存在栈内存和堆内存的对象;
 
 

⑫如何阻止表单提交?

在 onsubmit 事件中返回 return false;调用  event.preventDefault();效果一样。

 
 
 
 
Beautiful things don't ask for attention.美好的事物不要轻易惊扰。--来自2013年的《The Secret Life of Walter Mitty》
 
posted @ 2020-03-28 00:37  AZUKI七  阅读(299)  评论(0编辑  收藏  举报