资讯专栏INFORMATION COLUMN

为何jquery实例化的时候不需要new 一个构造函数

zorpan / 2550人阅读

摘要:为何构造函数不直接返回呢而是在中间搞了一个读过源码的都知道,这个函数实际是的初始化函数。

如题,这个问题我曾经在支付宝的电话面试里面最后一个问题被问到过,后来也没有去看到底为何不需要new,现在我们就来剖析下。
而且当你在看jquery源码的时候,如果一开始就搞不懂这样的问题,抑或jQuery.fn.init.prototype =jQuery.fn 这样的问题也搞不懂的话,那基本后面的东西都是懵的。

首先回顾下,我们一般是如何写插件的,通常是这样的

function Kissy () {
  
}

Kissy.prototype.alert = function () {
 
}
// 实例化必须要有,否则无法调用原型链上的alert方法
var kissy = new Kissy()
kissy.alert()
// 如果我们直接这样调用
Kissy().alert()
// 就会报错alert不是一个function。这里涉及到原型继承,new 一个构造函数和 执行普通函数的区别,不在赘述。

回归一个知识点,有助于我们理解后面我们讲解的内容

构造函数有return值怎么办?
构造函数里没有显式调用return时,默认是返回this对象,也就是新创建的实例对象。
当构造函数里调用return时,分两种情况:
1.return的是五种简单数据类型:String,Number,Boolean,Null,Undefined。
这种情况下,忽视return值,依然返回this对象。
2.return的是Object
这种情况下,不再返回this对象,而是返回return语句的返回值。

如何改造上面的代码,可以不用new函数,直接调用到alert方法呢?很简单。改造如下:

function Kissy () {
  return Kissy.prototype
}

当我们直接调用Kissy()函数的时候,不是返回的null或undefined而是返回Kissy的原型,即返回了一个原型对象,这个对象上是有alert方法的,这就好像我们熟悉的下面的代码一样

var obj = {
  name: "zj",
  getName: function() {
    console.log(this.name)
  }
}
obj.getName() // zj

接下来,我们仿造jquery源码又来改造下:

function Kissy () {
      return new Kissy.fn.init()
}
    
Kissy.fn = Kissy.prototype = {
  constructor: Kissy,
  init: function() {
      console.log("init")
  }
}

Kissy.fn.init.prototype = Kissy.fn

Kissy.fn.alert = function() {
    alert("0000")
}
Kissy().alert()  // 00000

无非就是在Kissy上面增加了一个fn属性,这个属性指向了Kissy.prototype。这样的目的是便于我们开发插件的时候,在原型上增加方法可以直接这么写Kissy.fn.alert 仅此而已。为何构造函数不直接返回
Kissy.fn呢 而是在中间搞了一个init.读过jquery源码的都知道,jquery.fn.init 这个函数实际是jquery的初始化函数。这里就不在展开了。

return new Kissy.fn.init()

构造函数返回了一个Kissy.fn.init()这个函数的一个实例。当然就会继承这个实例上的原型,而原型又被我们重置了

Kissy.fn.init.prototype = Kissy.fn

所以就能调用到Kissy.fn上面的alert方法了,不信大家可以试试哦。

再来看jquery的源码,对比刚刚分析的代码,是不是基本一模一样,只是jquery源码fn.init方法有比较多初始化的内容。

jQuery = function( selector, context ) {
    return new jQuery.fn.init( selector, context, rootjQuery );
},
jQuery.fn = jQuery.prototype = { //fn即对应prototype
    constructor: jQuery,
    init: function( selector, context, rootjQuery ) {
        ...
        return this;
    }
    ...
}
jQuery.fn.init.prototype = jQuery.fn;

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93879.html

相关文章

  • 求索:GSAP的动画快于jQuery吗?为何

    摘要:本文已完结,请看下文求索的动画快于吗为何续本文源自对问题动画性能优于的原理是什么的回答。是这样的吗请看下文求索的动画快于吗为何续 本文已完结,请看下文: > 求索:GSAP的动画快于jQuery吗?为何?/续 本文源自对问题《GSAP js动画性能优于jQuery的原理是什么?》的回答。GSAP是一个js动画插件,它声称20x faster than jQuery,是什么让...

    LiangJ 评论0 收藏0
  • 字节跳动前端一面试题及答案

    摘要:将构造函数的作用域赋值给新对象。也所以对象指向新对象执行构造函数内部的代码,将属性添加给中的对象。通常的解决方案是判断是否是构造函数的实例,若是则继续执行,若不是则进行的操作。代码如下在构造函数参数个数固定的情况下这种方案是可行的。 首先,一般的都是介绍自己,主要是项目经历 问题1:jQuery与Vue的区别是什么? JQuery和Vue的主要区别是JQuery主要是通过选择器来选取D...

    roundstones 评论0 收藏0
  • Spring IoC学习总结

    摘要:学习总结学习整理的一些笔记,很简单。大部分认为和只是不同的叫法而已。依赖注入的两种方式和注解使用注释驱动的功能源码剖析 Spring IoC学习总结 学习spring Ioc整理的一些笔记,很简单。分享给大家。 IoC 基本概念 在这之前,我们先记住一句话。好莱坞原则:Dont call us, we will call you.其实这句话很恰当地形容了反转的意味;Ioc, Inve...

    silencezwm 评论0 收藏0

发表评论

0条评论

zorpan

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<