一、问答题(50分)
    1、let和var的区别(6分)
    let、const:

    • 不存在变量提升。
    • 只能声明一次,不能重复声明
    • 变量声明出来存在VO(变量对象)或AO(活动对象)中,不会给window增加属性
    • 遇到大括号有块级作用域

    var:

    • 有变量提升
    • 在全局中声明的变量,会给window增加一个属性。

    2、call、bind、apply的区别(6分)
    call改变this并执行函数;bind改变this,但不会执行函数,会把改变this后的函数体返回;
    apply与call的传参方式不同,需要把传给F函数的参数放到一个数组(或者类数组)中传递进去
    3、构造函数与普通函数执行的区别(4分)
    构造函数执行之前,首先创建一个对象(创建一个堆内存,暂时不存储任何东西),并且让函数中的执行主体(this)指向这个新的堆内存(this===创建的对象)。
    执行完以后把this这个堆内存返回。
    4、构造函数执行,如果有return会怎么样(4分)
    return的是一个基本值,返回的结果依然是类的实例,没有受到影响
    return引用值,则会把默认返回值覆盖
    5、实现一个方法,检测该属性是否是该对象的公有属性。(10分)

    1. Object.prototype.hasPubProperty = function (attr) {
    2. let proto = Object.getPrototypeOf(this);
    3. while(proto){
    4. if(proto.hasOwnProperty(attr))return true;
    5. proto = Object.getPrototypeOf(proto);
    6. }
    7. return false;
    8. };

    6、类数组转数组的三种方式(3分)
    Array.from(arguments)
    […arguments]
    [].slice.call(arguments)
    7、如何能够让类数组使用forEach方法(2分)
    [].forEach.call(arguments,()=>{})
    8、描述原型链的机制(4分)
    原型链:属性的查找机制
    他是一种基于__proto__向上查找的机制。当我们操作实例的某个属性或者方法的时候,首先找自己空间中私有的属性或者方法
    找到了则结束查找,使用自己私有的即可
    没有找到,则基于__proto __找所属类的prototype,如果找到就用这个共有的,没有找到,基于原型上的__proto __继续向上查找,一直找到object.prototype 的原型为止,如果再没有,操作的属性或者方法不存在
    9、函数的三种角色(3分)
    普通函数、构造函数、普通对象
    10、Object的proto指向哪(2分)
    Function的原型
    11、手写map方法的实现原理(6分)

    1. Array.prototype.myMap = function (fn) {
    2. let res = [];
    3. for (let i = 0; i < this.length; i++) {
    4. res.push(fn(this[i], i));
    5. }
    6. return res;
    7. };

    二、基础编程(33分)
    1、下面代码的输出结果(3分)
    10 ‘zf’ 22

    1. let obj = {
    2. name:'zf',
    3. age:12,
    4. b:2
    5. };
    6. let {age=10,name='zhufeng',bb=22} = obj;
    7. console.log(age,name,bb)

    2、下面代码的输出结果(8分) 2 1 3 3

    1. var obj1 = {
    2. a: 1
    3. }
    4. var obj2 = {
    5. a: 2,
    6. foo1: function () {
    7. console.log(this.a)
    8. },
    9. foo2: function () {
    10. setTimeout(function () {
    11. console.log(this.a)
    12. }, 0)
    13. }
    14. }
    15. var a = 3
    16. obj2.foo1();//把foo1对应的函数执行,此时的this=>obj2 console.log(this.a)=>console.log(obj2.a)=>2
    17. obj2.foo1.call(obj1)//把foo1对应的函数执行 .call方法更改了方法中的this执行 this=>obj2=>更改为obj1 相当于console.log(obj.a)=>1
    18. obj2.foo2();//f002执行但是执行的是匿名函数,匿名函数中的this是全局下的window 相当于 console.log(this.a)=>console.log(window.a)=>3
    19. obj2.foo2.call(obj1)//虽然更改了foo2执行的this的执行,但是因为是匿名函数,匿名函数中的this是window同上

    3、下面代码输出的结果(6分)2 1 2 1

    1. function foo () {
    2. console.log(this.a);
    3. return function () {
    4. console.log(this.a);
    5. }
    6. }
    7. var obj = { a: 1 };
    8. var a = 2;
    9. foo();//=>this=>2 window window.a=>2
    10. foo.call(obj);//=>foo 1 执行 this更改为obj=>obj.a=>1
    11. foo().call(obj);//2 1 //=>foo执行的实例.call foo执行的时候this为window window.a=2 retrun的堆 0x001.call(obj)=>此时this更改为obj=>1

    4、下面代码输出的结果(6分)’zhufeng’ 5000 ‘zhufeng’ 9 9 5000

    1. function Person() {
    2. this.name = 'zhufeng';
    3. }
    4. Person.prototype.getName = function () {
    5. console.log(this.name);
    6. console.log(this.age);
    7. };
    8. Person.prototype.age = 5000;
    9. var per1 = new Person();
    10. per1.getName();
    11. per1.age = 9;
    12. per1.getName();//9
    13. console.log(per1.age);//9
    14. var per2 = new Person();
    15. console.log(per2.age);//5000

    1.png
    4、下面代码输出的结果(4分)0 30

    1. function fun() {
    2. this.a = 0;
    3. this.b = function () {
    4. alert(this.a);
    5. };
    6. }
    7. fun.prototype = {
    8. b: function () {
    9. this.a = 20;
    10. alert(this.a);
    11. },
    12. c: function () {
    13. this.a = 30;
    14. alert(this.a);
    15. },
    16. };
    17. var my_fun = new fun();
    18. my_fun.b();
    19. my_fun.c();

    2.png
    5、下面代码的输出结果(6分)2 4 1 1 2 3

    1. function Foo() {
    2. getName = function () {
    3. console.log(1);
    4. };
    5. return this;
    6. }
    7. Foo.getName = function () {
    8. console.log(2);
    9. };
    10. Foo.prototype.getName = function () {
    11. console.log(3);
    12. };
    13. var getName = function () {
    14. console.log(4);
    15. };
    16. function getName() {
    17. console.log(5);
    18. }
    19. Foo.getName();//2
    20. getName();//4
    21. Foo().getName();//1
    22. getName();//1
    23. new Foo.getName();//2
    24. new Foo().getName();//3

    无标题.png
    三、编程实战(17分)
    1、编写一个数组去重的函数,并且可实现数组调用(7分)
    数组去重的n种办法

    1. let ary = [12,23,12,13,13,12,23,14,8];
    2. ary.unique();//=>[12,23,13,14,8]去重后的新数组
    3. Array.prototype.unique = function() {
    4. let ary = [];
    5. this.forEach(item => {
    6. if(ary.indexOf(item)===-1) {
    7. ary.push(item)
    8. }
    9. })
    10. return ary
    11. }

    2、实现数字可调用方法,plus加法与minus减法(10分)

    1. let n = 10;
    2. let m = n.plus(10).minus(5);
    3. console.log(m);//=>15(10+10-5)
    4. Number.prototype.plus = function (num = 0) {
    5. return this + num;
    6. };
    7. Number.prototype.minus = function (num = 0) {
    8. return this - num;
    9. };