2024年最全面试官真的会问:new的实现以及无new实例化,学习web前端开发网站

JavaScript

  • js的基本类型有哪些?引用类型有哪些?null和undefined的区别。

  • 如何判断一个变量是Array类型?如何判断一个变量是Number类型?(都不止一种)

  • Object是引用类型嘛?引用类型和基本类型有什么区别?哪个是存在堆哪一个是存在栈上面的?

  • JS常见的dom操作api

  • 解释一下事件冒泡和事件捕获

  • 事件委托(手写例子),事件冒泡和捕获,如何阻止冒泡?如何组织默认事件?

  • 对闭包的理解?什么时候构成闭包?闭包的实现方法?闭包的优缺点?

  • this有哪些使用场景?跟C,Java中的this有什么区别?如何改变this的值?

  • call,apply,bind

  • 显示原型和隐式原型,手绘原型链,原型链是什么?为什么要有原型链

  • 创建对象的多种方式

  • 实现继承的多种方式和优缺点

  • new 一个对象具体做了什么

  • 手写Ajax,XMLHttpRequest

  • 变量提升

  • 举例说明一个匿名函数的典型用例

  • 指出JS的宿主对象和原生对象的区别,为什么扩展JS内置对象不是好的做法?有哪些内置对象和内置函数?

  • attribute和property的区别

  • document load和document DOMContentLoaded两个事件的区别

  • JS代码调试

  • 开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

所谓显式return,就是在构造函数中主动return一个对象,这里说的对象不仅包括Object,也包含ArrayDate等对象哦。

我们可以试一试:

function Test() {

this.name = ‘jack’;

this.age = 18;

return {

content: ‘我有freestyle’

}

}

new Test();

// Chrome控制台会输出以下内容

// {content: “我有freestyle”}

那么return一个普通类型数据有没有用呢?比如字符串,数字?试试便知。

function Test() {

this.name = ‘jack’;

this.age = 18;

return ‘我有freestyle’

}

new Test();

// Chrome控制台会输出以下内容

// Test {name: “jack”, age: 18}

可以看到,当我们return一个普通类型数据时,不会影响结果,依然会返回new出来的这个新对象。

我们也应该知道,new构造函数就是为了创建对象,你return一个字符串之类的普通类型数据是没有任何意义的,所以我们的关注点应该是return一个特殊的对象。请接着往下看。

无new实例化

=======

所谓“无new实例化”,就是指不通过new关键字实例化对象(当然,这里说的不通过new,只是调用层面的,底层还是用了new)。这一点我们使用jQuery的时候已经体验过了。

// 实例化了一个jQuery对象,但是没有用到new

var ele = jQuery(‘

freestyle
’);

那么这种黑科技是怎么实现的呢?

前面已经提到了,我们可以在构造函数中通过显式return来返回一个自定义的对象,那么这里就有发挥的空间了。我们通过一个简单的例子来感受下:

function Shadow() {

this.name = ‘jack’;

this.age = 18;

}

function jQuery() {

return new Shadow();

}

var obj1 = jQuery();

console.log(obj1)

// Chrome控制台会输出以下内容

// Shadow {name: “jack”, age: 18}

jQuery()用了移花接木的障眼法完成了对象实例化,一手隐藏的new Shadow()让我们误以为不用new直接调用函数也能创建实例。

我们再来试下new jQuery(),会发现,“卧槽,怎么跟jQuery()执行结果一模一样!”

var obj2 = new jQuery();

console.log(obj2)

// Chrome控制台会输出以下内容

// Shadow {name: “jack”, age: 18}

这是因为new构造函数显式return了new Shadow(),这样返回的结果也就是new Shadow()实例化出来的对象,而不使用new直接调用jQuery(),只是把jQuery()当成一个普通的函数执行,其结果不言而喻是new Shadow()实例化出来的对象。

所以,这里new jQuery()jQuery()是等价的。

虽然jQuery已经用得越来越少,但是其设计思路非常值得我们学习。那么jQuery到底妙在哪里?可以说是很多,链式操作,插件体系这些特色都是我们耳熟能详的。不扯太多了,就让我们来简单分析下jQuery实例化的过程。

我这里拿到了jQuery v1.12.4版本的代码,大概1W行,很舒服。

翻啊翻啊,翻到了第71行,看到了这么一串代码:

jQuery = function( selector, context ) {

return new jQuery.fn.init( selector, context );

}

这不就是我们熟悉的移花接木技术吗?jQuery.fn.init似乎就是上面例子中的Shadow。看着有点像了,但是还是要好好研究下。

为啥要搞个jQuery.fn?


jQuery.fn是jQuery.prototype的别名,是为了代码简洁的考虑。这一点参考源码第91行就可以知道。

jQuery.fn = jQuery.prototype = {

// …

移花接木如何保证原型指向?


我们知道,如果仅仅通过new jQuery.fn.init(selector, context)是存在一个问题的,问题就是得到的实例不是jQuery的实例,而是jQuery.fn.init的实例。那么如何处理这个问题呢?

我们翻到源码2866行,可以看到:

init = jQuery.fn.init = function( selector, context, root ) {

// 创建实例的具体逻辑

}

具体init方法怎么创建一个jQuery对象,做了哪些判断逻辑,这些都不是本文关注的重点。我们需要关注的是,jQuery是如何保证实例化的对象的原型指向是正确的?不然实例化的对象如何使用jQuery.prototype上面挂载的诸多方法呢,比如this.show()this.hide()

紧接着翻到2982行,我有了答案:

init.prototype = jQuery.fn;

妙啊,这一手修改原型指向的操作,完美解决了这个问题。这样一来,new init()得到的实例自然也是jQuery的实例。

jQuery.prototype.init.prototype === jQuery.prototype; // true

var a = $(‘

123
’)

a instanceof jQuery // true

a instanceof jQuery.fn.init // true

这样一来,我们可以得到一个基本的设计思路:

function myModule(params) {

return new myModule.fn.init(params);

}

myModule.fn = myModule.prototype = {

constructor: myModule

}

myModule.fn.init = function(params) {

// 可以对实例对象进行各种操作

}

myModule.fn.init.prototype = myModule.prototype;

在这个基础上,我们可以扩展静态方法和原型方法,这个myModule模块就变得越来越丰富。

刷面试题

刷题的重要性,不用多说。对于应届生或工作年限不长的人来说,刷面试题一方面能够尽可能地快速自己对某个技术点的理解,另一方面在面试时,有一定几率被问到相同或相似题,另外或多或少也能够为自己面试增加一些自信心,可见适当的刷题是很有必要的。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 前端字节跳动真题解析

  • 【269页】前端大厂面试题宝典

最后平时要进行自我分析与评价,做好职业规划,不断摸索,提高自己的编程能力和抽象思维能力。大厂面试远没有我们想的那么困难,摆好心态,做好准备,你也可以的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值