js原型和作用域面试考点总结

原型

  • 如何判断一个变量是不是数组
    该题考查原型和原型链,判断方法:
    • instanceof
    • Array.prototype.toString.call
    • Array.isArray
  • 手写一个简易的jquery,考虑插件和扩展性
(function name(params) {
    class jQuery {
        length = 0;
        constructor(selector) {
            const dom = document.querySelectorAll(selector);
            const length = dom.length;
            this.length = length;
            for (let index = 0; index < length; index++) {
                this[index] = dom[index];
            }
            return this
        }

        get(index) {
            return this[index]
        }

        each(fn) {
            const length = this.length
            for (let index = 0; index < length; index++) {
                const element = this[index];
                fn(element, index)
            }
        }

        on(type, fn, options) {
            options = options || false;
            return this.each(ele => {
                ele.addEventListener(type, fn, options)
            })
        }
    }

    class myJQuery extends jQuery {
        constructor(selector) {
            super(selector);
        }

        // 扩展方法
        css(property, value) {
            this.each(ele => {
                ele.style[property] = value
            })
        }
    }
    window.$ = function name(selector) {
        return new myJQuery(selector)
    }
})()
  • 原型本质,怎么理解
    原型即某对象的prototype,每个实例都有一个隐式原型__proto__和显示原型prototype;当实例调用实例方法时,会先再自己的__proto__找到该对象,然后进行对应方法的查找,若不存在则向上以及的原型查找直到找到该方法或Object,即Object就是所有实例最终的prototype,Object的prototype指向null
  • 手写圣杯模式继承
    圣杯模式继承即不实现直接继承,通过临时的function作为中间者,当给son的prototype增加属性时不会影响father。
var inherit = (function () {
    function __tempFunc() { }
    return function(Target, Origin){
        __tempFunc.prototype = Origin.prototype;
        Target.prototype = new __tempFunc(); // target.__proto__ => Origin.prototype
        Target.prototype.constructor = Target;
        Target.prototype.uber = Origin.prototype
    }
})()
class

class是function的语法糖,简化了function创建和继承的一系列操作。

  • constructor
  • 属性
  • 方法
    举个例子:
class Person {
    name = '张三'
    constructor (name) {
        this.name = name
    }

    speak (lang) {
        console.log(lang)
    }
}
// 通过new关键字创建实例
var person1 = new Person('李四');
person1.speak('en');
继承和类型判断
  • 继承
class People {
    constructor(name) {
        this.name = name;
    }
    eat() {
        console.log(this.name + ' is eating something');
    }
}

class Student extends People {
    constructor(name, number) {
        super(name);
        this.number = number;
    }

    sayHi(){
        console.log('hi')
    }
}

class Teacher extends People {
    constructor(name, major) {
        super(name);
        this.major = major;
    }

    teach(){
        console.log('hi')
    }
}
const teaWang = new Teacher('王', '语文');
const stuXia = new Teacher('夏', '222222');
teaWang.number; // undefined
teaWang.major; // 语文
stuXia.major; // undefined
  • 类型判断
    在javascript类型中,array是继承于Object的,可以用instanceof进行引用类型的判断,instanceof可以用于判断原型链上的继承关系。
stuXia instanceof Student // true
stuXia instanceof People // true
stuXia instanceof Object // true

[] instanceof Array // true
[] instanceof Object // true

{} instanceof Object // true

作用域

  • this的不同应用场景,如何取值
  1. 在class方法中调用:this是class
  2. 箭头函数:this是上级作用域
  3. 作普通函数被调用:this是window
  4. 使用call、apply、bind:this是第一个参数
  5. 作为class方法被调用:this是class
    注意:this指向是在函数执行的时候确认而非函数定义的时候确认
    举个例子:
function fn() {
    console.log(this)
}

fn();  // window

fn.call({x: 1000}); // {x: 1000}

const fn1 = fn.biond({x: 200});
fn1(); // {x: 200}
  • 手写bind、apply、call函数
function fn(a, b, c, d) {
    console.log('this', this);
    console.log(a, b, c, d);
    return 'this is fn'
}

function transformArrayLikeToArray(arrLike) {
    return Array.prototype.slice.call(arrLike)
}

Function.prototype.bind1 = function () {
    const args = transformArrayLikeToArray(arguments);
    const self = this; // current fn
    const context = args.shift();
    return function () {
        const __args = transformArrayLikeToArray(arguments);
        return self.apply(context, args.concat(__args))
    }
}

Function.prototype.apply1 = function () {
    const args = transformArrayLikeToArray(arguments);
    const self = this; // current fn
    const context = args.shift();
    const tempFn = self.bind(context, ...args[0]);
    return tempFn()
}


Function.prototype.call1 = function () {
    const args = transformArrayLikeToArray(arguments);
    const self = this; // current fn
    const context = args.shift();
    const tempFn = self.bind(context, ...args);
    return tempFn()
}
  • 实际开发中闭包的应用场景,举例说明
  1. 隐藏数据
  2. 简单做一个cache工具,举个例子:
function createCache() {
    const data = {};
    return {
        set: function (key, val) {
            data[key] = val
        },
        get: function (key) {
            return data[key]
        }
    }
}

const cache = createCache();
cache.set('a', 10);
cache.get('a'); // 10
  • 创建10个a标签,点击的时候弹出对应的序号,代码如下:
   var fragment = document.createDocumentFragment();
    for (var i = 0; i < 10; i++) {
        (function (i) {
            var _a = document.createElement('a');
            _a.innerHTML = i + '<br />';
            _a.addEventListener('click', function (e) {
                e.preventDefault();
                alert(i)
            });
            fragment.appendChild(_a)
        })(i)
    }
    document.body.appendChild(fragment)
知识点
  • 作用域:
    作用域有全局作用域、函数作用域、块级作用域,变量的使用不能逃出当前所在的作用域之外。

  • 自由变量:
    一个变量再当前作用域没有定义,但被使用了就会向上一级作用域一次寻找,直到被找到为止;如果到了全局作用域还未被找到,则报错。
    注意:自由变量的查找,是在函数定位的地方,向上级查找,不是在函数执行的地方!!!

  • 闭包:
    闭包是函数作用域二点特殊情况,有两种表现:

    • 函数作为参数被传递
    • 函数作为返回值被返回

    举个例子

    // 函数作为返回值被返回
    function create(){
        let a = 100;
        return function () {
            console.log(a)
        }
    }

    let fn = create();
    let a = 200;
    fn(); // 100

    // 函数作为参数被传递
    function print(fn) {
        let a = 200;
        fn()
    }

    let a = 100;
    function fn() {
        console.log(a)
    }

    print(fn); // 100
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值