当前位置: 首页 > news >正文

JavaScript原型的实际应用

原型是javascript的核心概念也是较难理解的,本篇主要介绍原型的一些概念,且与构造函数属性、构造函数方法的区别,最后结合Jquery与Zepto在实际工作中的应用进行分析介绍,希望对您有帮助。

快速导航

  • 原型概念
    • 原型模式的执行流程
    • 构造函数实例属性方法
    • 构建原型属性方法
  • 原型字面量创建对象
    • 字面量创建对象
    • 构造函数创建对象
    • 原型对象的重写需要注意的问题
  • 原型的实际应用
    • jquery中原型应用
    • zepto中原型的应用
  • 原型的扩展

原型概念

我们所创建的每个原型都有一个(原型)属性,这个属性是一个对象。

原型模式的执行流程

  1. 先查找构造函数实例里的属性或方法,如果有,立刻返回
  2. 如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回

构造函数实例属性方法

function Box(name,age){
    this.name=name; 	//实例属性
    this.age=age;
    this.run=function(){ //实例方法
        return this.name+this.age+"运行中.....";
    };
}

var box1=new Box('zhangsan',20);
var box2=new Box('lisi',18);
alert(box1.run==box2.run); //false
复制代码

构建原型属性方法

构造函数体内什么都没有,这里如果有,叫作实例属性,实例方法

function Box(){}
复制代码
Box.prototype.name='lee'; //原型属性
Box.prototype.age=23;
Box.prototype.run=function(){//原型方法
    return this.name+this.age+"运行中......";
};
复制代码

如果是实例化方法,不同的实例化,他们的地址是不一样的,是唯一的,如果是原型方法,那么他们地址是共享的,大家都一样,看以下示例box1.run==box2.run

var box1=new Box();
var box2=new Box();
alert(box1.run==box2.run);  // true
复制代码

这个属性是一个对象,访问不到

alert(box1.prototype);
复制代码

这个属性是一个指针指向prototype原型对象

 alert(box1._proto_);
复制代码

构造属性可以获取构造函数本身,作用是被原型指针定位,然后得到构造函数本身,其实就是对象实例对应的原型对象的作用

alert(box1.constructor);
复制代码

原型字面量创建对象

使用构造函数创建原型对象和使用字面量创建对象在使用上基本相同,但还是有一些区别,字面量创建的方式使用constructor属性不会指向实例,而会指向Object,构造函数则相反。

字面量创建对象

function Box(){}
复制代码

使用字面量的方式创建原型对象,这里{}就是对象(Object),new Object就相当于{}

Box.prototype={
    name:'lee',
    age:20,
    run:function(){
        return this.name+this.age+"运行中.......";
    }
};

var box1=new Box();
alert(box1.constructor);//返回function Object(){}对象
复制代码

构造函数创建对象

function Box(name,age){
    this.name=name;
    this.age=age;
    this.run=function(){
        return this.name+this.age+"运行中....";
    };
}

var box1=new Box('zhangsan',20);
alert(box1.constructor); //返回的是function Box(){}
复制代码

原型对象的重写需要注意的问题

  1. 重写原型对象之后,不会保存之前原型的任何信息
  2. 把原来的原型对象和构造函数对象实例之间的关系切断了
function Box(){}

Box.prototype={
    constructor:Box,//让它强制指向Box
    name:'lee',
    age:20,
    run:function(){
        return this.name+this.age+"运行中.......";
    }
};
复制代码

重写原型

Box.prototype={
    age:21
}
var box1=new Box();
alert(box1.name); // undefined
复制代码

可以使用addstring()方法向原型添加内容,这样可以避免原型重写

String.prototype.addstring=function(){
    return this+',被添加了!';
};

var box1=new Box();
alert(box1.name.addstring()); // lee,被添加了!
复制代码

原型的实际应用

  1. 先找到入口函数window.$
  2. 根据入口函数找到构造函数new ...
  3. 根据构造函数找到原型的定义zepto.Z.prototype

实例

以下实例中通过Jquery或Zepto操作dom元素,例如css方法、text方法都是操作的原型上的的方法。

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Zepto</title>
    <!--<script src="https://cdn.bootcss.com/zepto/1.1.6/zepto.js"></script>
    <script src="zepto.js"></script>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> -->
    <script src="jquery.js"></script>
</head>
<body>
    <div> 这是一个测试 </div>
    <div> 这是一个测试2 </div>
    <script>
        var div = $('div'); // 得到一个实例
        div.css('color', 'red'); // 原型方法css
        alert(div.text()); // 原型方法text
    </script>
</body>
</html>
复制代码

zepto中原型的应用

Zepto源码地址:cdn.bootcss.com/zepto/1.1.6…

以下实例也是取了关于原型部分的源码

var Zepto = (function() {
    var $, zepto={}, emptyArray=[], slice=emptyArray.slice, document=window.document;

    // 构造函数
    zepto.Z = function(dom, selector) {
        dom = dom || []
        dom.__proto__ = $.fn
        dom.selector = selector || '';

        return dom
    }

    zepto.init = function(selector) {
        var dom;

        // 如果选择器不存在,返回一个空的Zepto集合
        if (!selector) return zepto.Z();

        // 优化字符串选择器
        if (typeof selector === 'string') {
            selector = selector.trim();

            // 还有一系列的判断此处忽略,进行简化 ...
            dom = slice.call(document.querySelectorAll(selector))
        } else {
            // 更多可以去查看源码 ...
        }

        return zepto.Z(dom, selector)
    }

    $ = function(selector) {
        return zepto.init(selector);
    } 

    $.fn = {
        text: function() {
            return (0 in this ? this[0].textContent : null)
        },
        css: function() {
            alert('css');
        }
    }

    // $.fn赋值给构造函数的原型
    zepto.Z.prototype = $.fn;

    return $;
})()

window.Zepto = Zepto;
window.$ === undefined && (window.$ = Zepto); // 如果window.$不存在,赋予window.$为Zepto;
复制代码

jquery中原型应用

Jquery源码地址:cdn.bootcss.com/jquery/3.3.…

(function(global, factory) {
    // 浏览器环境、Node环境判断
    if ( typeof module === "object" && typeof module.exports === "object" ) {
        // Node环境处理,这里不做阐述,具体参考源码
        // factory(global, true);
    } else {
        // 进入浏览器环境
        factory(global);
    }
})(typeof window !== "undefined" ? window : this, function(window, noGlobal) {
    var Jquery = function(selector) {
        return new jQuery.fn.init(selector);
    }

    Jquery.fn = Jquery.prototype = {
        css: function() {
            alert('css');
        },
        text: function() {
            return (0 in this ? this[0].textContent : null);
        }
    };

    // 定义构造函数
    var init = Jquery.fn.init = function(selector) {
        var slice = Array.prototype.slice;
        var dom = slice.call(document.querySelectorAll(selector));

        var i, len=dom ? dom.length : 0;
        for (i=0; i<len; i++) {
            this[i] = dom[i];
        }
        this.length = len;
        this.selector = selector || '';
    }

    // 构造函数原型赋值
    init.prototype = Jquery.fn;

    if ( !noGlobal ) { // 判断是否为浏览器环境
        window.jQuery = window.$ = Jquery;
    }    
})
复制代码

原型的扩展

  1. 插件扩展在$.fn之上,并不是扩展在构造函数的原型
  2. 对外开放的只有$,构造函数并没有开放

在Zepto中把原型方法放在$.fn上,在Jquery中把原型方法放在Jquery.fn之上,之所以这样做是为了后期插件扩展所需。

实例:

<body>
    <script>
        // 插件扩展:获取tagName
        $.fn.getTagName = function() {
            return (0 in this ? this[0].tagName : '');
        }    
    </script>
    <div> 这是一个测试 </div>
    <div> 这是一个测试2 </div>
    <script>
        var div = $('div'); // 得到一个实例
        alert(div.getTagName()); // 封装的插件
    </script>
</body>
复制代码

作者:五月君
链接:www.imooc.com/article/270…
来源:慕课网
Github: 技术博客

相关文章:

  • 微软宣布Azure Function支持Python
  • adb
  • java监控工具VisualVM
  • linux学习day3
  • 10.linux命令之cal命令
  • 孔乙己的疑问:单例模式有几种写法
  • VBScript:WshShell对象
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • 任正非公开信深度解读:两年怎样改变了华为?
  • 华为:两年前要炸掉研发金字塔,今天要投入20亿美元提升软件质量
  • linux之常用命令的使用
  • CF1096E.The Top Scorer[概率期望]
  • 老司机 iOS 周报 #51 | 2019-01-07
  • 华为重磅发布芯片,领衔开启2019 CES,一文看尽五大硬核亮点
  • Sping boot和mybatis整合
  • ----------
  • 5、React组件事件详解
  • Angular Elements 及其运作原理
  • Gradle 5.0 正式版发布
  • JavaScript 一些 DOM 的知识点
  • JavaScript函数式编程(一)
  • java中具有继承关系的类及其对象初始化顺序
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • Python 基础起步 (十) 什么叫函数?
  • rc-form之最单纯情况
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 从tcpdump抓包看TCP/IP协议
  • 翻译:Hystrix - How To Use
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 爬虫模拟登陆 SegmentFault
  • 漂亮刷新控件-iOS
  • 使用 @font-face
  • 因为阿里,他们成了“杭漂”
  • 优化 Vue 项目编译文件大小
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • 阿里云API、SDK和CLI应用实践方案
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • #1014 : Trie树
  • #mysql 8.0 踩坑日记
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (转)ObjectiveC 深浅拷贝学习
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET DataGridView数据绑定说明
  • .Net 知识杂记
  • .NET中GET与SET的用法
  • [ HTML + CSS + Javascript ] 复盘尝试制作 2048 小游戏时遇到的问题
  • []sim300 GPRS数据收发程序
  • []常用AT命令解释()
  • [20180224]expdp query 写法问题.txt
  • [Android]使用Git将项目提交到GitHub
  • [Android学习笔记]ScrollView的使用