🔒 JS高级基础知识考试

原型链
new命令的作用,以及new命令中的this
json和javascript
MVC的概念
ES5实现类
Promise的使用

填空题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var object = {}
object.__proto__ === ????填空1???? // 为 true
var fn = function(){}
fn.__proto__ === ????填空2???? // 为 true
fn.__proto__.__proto__ === ????填空3???? // 为 true
var array = []
array.__proto__ === ????填空4???? // 为 true
array.__proto__.__proto__ === ????填空5???? // 为 true
Function.__proto__ === ????填空6???? // 为 true
Array.__proto__ === ????填空7???? // 为 true
Object.__proto__ === ????填空8???? // 为 true
true.__proto__ === ????填空9???? // 为 true
Function.prototype.__proto__ === ????填空10???? // 为 true

答:

  1. Object.prototype
  2. Function.prototype
  3. Object.prototype
  4. Array.prototype
  5. Object.prototype
  6. Function.prototype
  7. Function.prototype
  8. Function.prototype
  9. Boolean.prototype
  10. Object.prototype

构造函数,new命令中的this

1
2
3
4
function fn(){
console.log(this)
}
new fn()

new fn() 会执行 fn,并打印出 this,请问这个 this 有哪些属性?这个 this 的原型有哪些属性?
答:
这里的this指向fn的实例对象,此处是一个空对象,因此这个this没有什么属性。
this 的原型有constructor 属性,以及从Object.prototype继承的属性

知识点         

在构造函数或者构造函数原型对象中this指向构造函数的实例
所谓”构造函数”,就是专门用来生成实例对象的函数。
new命令的作用,就是执行构造函数,返回一个实例对象。
new命令做了以下几件事:

  1. 创建一个空对象,作为将要返回的对象实例。
  2. 将这个空对象的原型,指向构造函数的prototype属性。
  3. 将这个空对象赋值给函数内部的this关键字。(this指向这个自动生成的空对象)
  4. 然后执行构造函数内部的代码。
    构造函数之所以叫“构造函数”,就是说这个函数的目的,就是操作一个空对象(即this对象),将其“构造”为需要的样子。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //不使用new指向window
    function Person (name) {
    console.log(this); // window
    this.name = name;
    }
    Person('inwe');
    //使用new
    function Person (name) {
    this.name = name;
    console.log(this); // xxx
    self = this;
    }
    var xxx = new Person('iwen');
    console.log(self === xxx) //true
    //这里new改变了this指向,将this由window指向Person的实例对象xxx

new 操作为了记录「空对象是由哪个构造函数创建的」,所以会自动给「构造函数.prototype」加了一个 constructor 属性: constructor 属性返回对象的构造函数。 返回值是函数的引用(比如数组 constructor 属性返回 function Array() { [native code] }),而不是函数名:

1
2
3
4
5
6
7
function P(){
console.log(this);
}
var x = new P();
P.prototype.constructor === P // true
x.constructor === P // true
p.constructor === P.prototype.constructor // true

constructor属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的。

1
2
var x = new Array(1,2,3);
x.constructor === Array // true

Object的共有属性
所有对象都继承了Object.prototype的属性。这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。

JSON 和 JavaScript

JSON 和 JavaScript 是什么关系?
JSON 和 JavaScript 的区别有哪些?
答:
关系:

  • JS 是一门语言,JSON 是另一门语言
  • json这门语言是道格拉斯抄袭js的语言
  • JSON 使用 Javascript语法来描述数据对象
  • 道格拉斯还写了本《javascript语言精粹》,俗称蝴蝶书,来吐槽js中垃圾的地方

区别:
json里的字符串必须用双引号,不能用单引号!
json没有undefinedfunction
| js语法 | json语法 |
| :—-: |:———:|
| 123 | 123 |
| ‘stage’ | “stage” |
| true | true |
| [‘a’, ‘b’] | [“a”, “b”] |
| {name: ‘stage’} | {“name”: “stage”} |
| null | null |
| undefined | json没有undefined |
| function fn(){} | json没有function |

此外,JSON有2个api,分别是JSON.parse(str)和JSON.stringify(obj)

前端 MVC

前端 MVC 是什么?
请用代码大概说明 MVC 三个对象分别有哪些重要属性和方法。(不用写详细代码,只需要说明重要属性的名称即可)
MVC是一种设计模式

  • Model(模型)- 通常模型对象负责在数据库中存取数据。
  • View(视图) - 通常视图是将模型里的数据可视化。
  • Controller(控制器) - 从视图读取数据,控制用户输入,并向模型发送数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
var model = {
fetch: function(){
/* 获取服务端数据 */
}
save: function(data){
/* 将数据保存到服务端 */
}
}
var view = document.querySelector('xxx');
var controller = {
view: null,
model: null;
init: function(view,model){
this.view = view;
this.model = model;
this.form = view.querySelector('form');
this.getData();
this.saveData();
this.bindEvent();
},
getData: function(){
this.model.fetch().then(function(){});
},
saveData: function(){
this.model.save(data).then(function(){})
},
bindEvent: function(){
this.form.addEventListener('submit', function(ev){
ev.preventDefault();
this.saveData();
})
}
}
controller.init(view, model);
```
# 在 ES5 中如何用函数模拟一个类?
```javascript
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}
Person.prototype.country = 'china';
var zs = new Person("张三","29","teacher");
var ls = new Person("李四","22","doctor");
zs.name // 张三
zs.age // 29
ls.job // doctor
zs.country // china
ls.country // china

关于Promise

用过 Promise 吗?举例说明。
如果要你创建一个返回 Promise 对象的函数,你会怎么写?举例说明。
答:
Promise的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$.get(url).then(function(data){console.log(data)},function(){console.log('失败')});
```
创建:
```javascript
function preloadImage(path) {
return new Promise(function (resolve, reject) {
var image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
});
};
preloadImage('/xxx.jpg')
.then(function(){console.log('成功')},
function(){console.log('失败')});

知识点

Promise 对象是 JavaScript 的异步操作解决方案,从而不必一层层地嵌套回调函数endFn。
传统的写法可能需要把f2作为回调函数传入f1,比如写成f1(f2),异步操作完成后,在f1内部调用f2。Promise 使得f1和f2变成了链式写法。不仅改善了可读性,而且对于多层嵌套的回调函数尤其方便。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 传统回调写法
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// ...
});
});
});
});
回调地狱!!
// Promise 的写法
(new Promise(step1))
.then(step2)
.then(step3)
.then(step4);

创建一个返回 Promise 对象的函数:

1
2
3
4
5
6
7
8
9
10
11
function preloadImage(path) {
return new Promise(function (resolve, reject) {
var image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
});
};
preloadImage('/xxx.jpg')
.then(function(data){console.log('成功');console.log(data)}, function(data){console.log('失败');console.log(data)});

Promise 对象的状态

Promise 对象通过自身的状态,来控制异步操作。Promise 实例具有三种状态。

  • pending等待态: 初始状态,既不是成功,也不是失败状态。
  • fulfilled完成态: 异步操作成功。
  • rejected拒绝态: 异步操作失败。

上面三种状态里面,fulfilled和rejected合在一起称为resolved(已定型)。
这三种的状态的变化途径只有两种。

  • 从“未完成”到“成功”
  • 从“未完成”到“失败”

一旦状态发生变化,就凝固了,不会再有新的状态变化。这也是 Promise 这个名字的由来,它的英语意思是“承诺”,一旦承诺成效,就不得再改变了。这也意味着,Promise 实例的状态变化只可能发生一次。

因此,Promise 的最终结果只有两种。

  • 异步操作成功,从 pending 变为 fulfilled
  • 异步操作失败,从 pending 变为 rejected。

只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

一开始,我们先设置好等状态从 pending 变成 fulfilled 和 rejected 的预案(当成功后我们做什么,失败时我们做什么)。

Promise 启动之后,当满足成功的条件时我们让状态从 pending 变成 fullfilled (执行 resolve);当满足失败的条件,我们让状态从 pending 变成 rejected(执行 reject)

Promise简单理解

原始写法:       

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function fn1(callback) {
setTimeout(()=>{
console.log('fn1')
callback()
}, 1000)
}
function fn2(callback) {
setTimeout(()=>{
console.log('fn2')
callback()
}, 1000)
}
function fn3() {
setTimeout(()=>{
console.log('fn3')
}, 1000)
}
回调地狱↓
fn1(function(){
fn2(function(){
fn3()
})
})
//fn1,fn2,fn3

Promise写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function fn1() {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
console.log('fn1...')
resolve();
}, 1000)
})
}
function fn2() {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
console.log('fn2...')
resolve();
}, 1000)
})
}
function fn3() {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
console.log('fn3...')
resolve();
}, 1000)
})
}
function onerror() {
console.log('error')
}
fn1()
.then(fn2)
.then(fn3)
.catch(onerror)


Promise快速用法:

1
2
3
$.get('https://www.xxx.com/')
.then((data)=>console.log(data),
(error)=>{console.log(error);document.write(error.responseText)})

-------------本文结束感谢您的阅读-------------