官方文档

请回答以下问题

Java和JavaScript什么关系?

1
最初的 JavaScript 名为 LiveScript,后来因为 Sun Microsystem 的 Java 语言的兴起和广泛使用,Netscape 出于宣传和推广的考虑,将它的名字从最初的 LiveScript 更改为 JavaScript——尽管两者之间并没有什么共同点。这便是之后混淆产生的根源。

ES6听说过吗?和JavaScript什么关系?ES2015听说过吗?都是什么关系?

1
ES6是JavaScript的第六版,因为在2015年发布,所以也称ES2015

如何把变量转成数字?转成布尔?转成字符串?

1
2
3
4
5
转数字
parseInt:如果前几个字符是数字可以转成数字。
Number:将整体转成数字。
。。。。
其他的我觉得没什么好转的

使用 Number() 和 parseInt 转数字时的区别?

1
如上...

var 和 let 干什么用的?什么区别?

1
2
3
4
5
都是定义变量的
var 可以定义局部变量和全局变量
let 可以定义快级变量(只在大括号中生效的变量)、局部变量和全局变量
一般在函数外部多使用var 来定义变量,在函数和循环内多试用let来定义变量
var 支持变量提升,let不支持

在一个函数中,如果定义变量时没有添加 var 会出现什么情况?

1
如果在函数中定义变量时没有写 var 或者 let 那么变量会变成全局变量。

什么是内存泄漏?

1
应该当作垃圾回收结果无法被释放,导致一直占用内存。这种行为被成为内存泄露

什么是块级作用域?如何定义块级作用域的变量?

1
在大大括号内的,一般用let定义块级变量

你需要带着问题,看下面的内容

什么是运算符短路?有什么用?
说出JS中你用过的数据类型?
编写一个使用 let 定义变量和使用 var 定义变量不同点的案例。
for .. in 和 for .. of 的区别?用途?
forEach 的用途?
请问 arguments 是干什么用的?它代表什么?
什么是匿名函数?应用场景?
this 代表什么?
什么是箭头函数?有什么用途?this 在箭头函数和普通函数中的区别是什么?
call 和 apply 的功能是什么?有什么区别?
如何开启严格模式?请说出至少一个严格模式与普通模式的区别?
什么是闭包?闭包有什么特点?有什么用?
什么是垃圾回收机制?
什么是内存泄漏?在什么情况下会出现内存泄漏?
什么是OOP?OOP的三大特性?什么是多态?
什么是原型链?对象如何访问原型对象?构造函数如何访问原型对象?
什么是构造函数?在JS中如何基于原型(prototype)实现面向对象?
ES6中的OOP中 super 是干什么用的?ES6中的继承需要注意什么?

介绍

数据类型

类型转换

转数字

parseInt:如果前几个字符是数字可以转成数字。
Number:将整体转成数字。

1
2
3
var num = '123abc';
console.log( parseInt(num) ); // 123
console.log( Number(num) ); // NaN (Not a Number)

转字符串

1
2
console.log( 100 + 100 + '100abc');        // 200100abc
console.log( '' + 100 + 100 + '100abc'); // 100100100abc

变量

定义变量:varlet

定义常量:const

var

可以定义 局部变量全局变量

1
2
3
4
var name;   // 全局变量
function abc() {
var age; // 局部变量
}

意外的全局变量。
如果在函数中定义变量时没有写 var 或者 let 那么变量会变成全局变量。

1
2
3
4
5
6
function abc() {
age = 10 // 全局变量
}
abc()

console.log( age ) // 10

let

可以定义块级变量局部变量全局变量

let 可以定义块级变量(只在大括号中生效的变量)

示例1:let 和 var 的区别

1
2
3
4
5
6
7
8
9
10
for(let i=0;i<10;i++) {

}
console.log( i ) // undefined


for(var i=0;i<10;i++) {

}
console.log( i ) // 10

示例2:使用 var 时无论,调用数组中第几个函数,输出的结果都是10

1
2
3
4
5
6
7
8
9
var funs = []
for(var i=0;i<10;i++) {
funs[i] = function() {
console.log( i )
}
}
funs[3](); //10
funs[4](); //10
funs[5](); //10

使用 let 时的效果:

1
2
3
4
5
6
7
8
9
var funs = []
for(let i=0;i<10;i++) {
funs[i] = function() {
console.log( i )
}
}
funs[3](); // 3
funs[4](); // 4
funs[5](); // 5

短路运算符

我们可以使用 &&|| 实现短路操作。

&& : 连接多个语句,当语句1为真是执行语句2.

||:连接多个语句,当语句1为假时执行语句2.

可以用短路运算符来实现一些简写,比如,有时我们获取到一个变量,不知道它的值是什么,但我们希望无论如何它都是一个数字,至少是个0,我们就可以写:

1
2
// 如果 a 是假就得到0
var a = a || 0
1
2
// 如果 o 存在就调用 o.name
o && o.name()

循环

除了 while、do…while、for 之外,我们还可以使用:

  1. 在循环数组时,我们可以使用 for...offor...inforEach

  2. 循环对象时,我们可以使用 for...in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let arr = ['a','b','c','d','e']

// 循环得到值
for(let i of arr) {
console.log(i) // abcde
}

// 循环得到下标
for(let i in arr) {
console.log(i) // 01234
}

// 循环得到下标和值
arr.forEach((v,k)=>{
console.log(k,v) // 0a1b2c3d4e
})

函数

arguments

在函数中可以使用 arguments 获取函数在调用时的参数数组。

1
2
3
4
5
6
function abc() {
console.log( arguments.length ) // 2 , 获取参数的数量
console.log( arguments[0] ) // tom ,第一个参数值
console.log( arguments[1] ) // jack ,第二个参数值
}
abc('tom','jack')

匿名函数

匿名函数可以用来隔绝一段作用域。

有时我们需要在一个现有的项目中添加新的代码,这时当我们添加变量、函数时就有可能出现和原来系统中变量名、函数名冲突的情况,为了避免我们的代码和原代码中出现命名冲突的情况,我们就可以把我们的代码放到一个匿名函数中,然后调用这个匿名函数,这样我们所写的代码都只在这个匿名函数内生效,就不会影响其它代码了。

有两种写法,来调用匿名函数得到一段独立的作用域:

1
2
3
4
5
6
7
8
9
10
11
(function(){

// 这里的代码不影响外面的作用域

})()

!function(){

// 这里的代码不影响外面的作用域

}()

箭头函数

箭头函数是匿名函数的一种简写方式。

1
2
3
4
5
6
7
8
9
// 普通函数
setTimeout(function(){
console.log( 'hello' )
}, 1000)

// 箭头函数
setTimeout(()=>{
console.log( 'hello' )
}, 1000)

比如以下代码运行的结果是不同的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var age = 20

function abc() {
this.age = 10

setTimeout(function(){
console.log( this.age ) // 20
}, 1000)

setTimeout(()=>{
console.log( this.age ) // 10
}, 1000)
}

abc()

call/apply

call 和 apply 的功能相同:使一个函数归属于一个对象来调用

1
2
3
4
5
6
7
8
function abc() {
console.log( this.age )
}
var o = {
age:10
}
abc(); // 独立调用时 this.age 不存在
abc.call(o); // 10 , abc 函数归属于 o 这个对象来调用,这时 this.age 指的就是 o 对象中的 age。

call 和 apply 的区别是参数形式不同:

1
2
3
4
5
6
7
8
function abc(a,b) {
console.log( this.age )
}
var o = {
age:10
}
abc.call(o, 10, 20); // 10 , 20 对应 a, b 两个参数
abc.apply(o, [10,20]); // [10,20] 数组中的对应 a,b 两个参数

严格模式


以下代码在严格模式下会报错:

1
2
3
4
5
6
7
'use strict'      // 严格模式

function abc() {
age = 'tom' // 报错
}

abc();

闭包

以下代码就是一个闭包,它制作了一个 id 变量,这个变量不会马上销毁,会一直存在,并且不能被外部随意修改,只能通过闭包内修改。

1
2
3
4
5
6
7
8
9
10
11
12
// 定义闭包
function getId() {
var id = 0;
return function() {
return id++;
}
}
// 获取一个自增的ID
var id = getId()
console.log( id() ) //0
console.log( id() ) //1
console.log( id() ) //2

内存泄漏

循环引用

当 DOM 对象和 JS 对象互相引用时,会导致两个对象在该销毁时都无法销毁。

比如下面的 el 和 o 这两个对象都是局部变量,在函数执行之后就应该销毁,但因为两个对象互相引用,所以导致函数执行之后也无法销毁:

原型链

原型链:所有的对象都会继承自一个原型对象,这个原型对象又会继承自一个原型对象,一层一层直到最顶层继承自 null,这样的链就是原型链。

构造函数:生成对象的函数。

访问原型对象

对象中通过 __proto__ 访问原型对象。

构造函数中通过 prototype 访问原型对象。

基于原型链的面向对象

JS 在实现面向对象编程时传统的方法是基于原型链+构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 定义一个类
function Person(name, age) {
this.name = name
this.age = age
}

// 在原型对象上添加方法
Person.prototype.setName = function(name) {
this.name = name
}
Person.prototype.getName = function() {
return this.name
}
// 生成对象
var p1 = new Person('tom',10)
console.log( p1.getName() ); // tom

JS 中实现面向对象编程的原则:

  1. 属性定义到构造函数中
  2. 方法定义到原型对象上(避免每个对象都拷贝一份函数)

ES6 中的面向对象

ES6 中提供了 class 可以实现面向对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person
{
// 构造函数
constructor(name,age) {
this.name = name
this.age = age
}

getName() {
return this.name
}

setName(name) {
this.name = name
}
}

var p1 = new Person('tom',10)
console.log( p1.getName() ) // tom

继承

在原型统的 JS 中我们使用原型对象实现继承,在 ES6 中我们可以使用 extends 实现类的继承。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Person
{
// 构造函数
constructor(name,age) {
this.name = name
this.age = age
}

getName() {
return this.name
}

setName(name) {
this.name = name
}
}
// 继承自 Person
class Boy extends Person {

}

super

在继承时,如果子类中定义了构造函数,那么在构造函数中必须要调用 super 方法来调用父类的构造函数。
~~~js
class Person
{
// 构造函数
constructor(name,age) {
this.name = name
this.age = age
}
getName() {
return this.name
}

setName(name) {
    this.name = name
}

}
// 继承自 Person
class Boy extends Person {
constructor(name, age) {
// 调用父类的构造函数
super(name, age)
}
}

 评论



本站使用 Material X 作为主题 , 总访问量为 次 。
隐藏