JavaScript MVC 学习笔记(三)类的使用(中)

编辑
• 阅读 3458

公开记录学习JS MVC,不知道能坚持多久= =。以《基于MVC的JavaScript web富应用开发》为主要学习资料。接上一篇类的学习,发现实在是看晕了,有些例子是能看懂在干嘛,但是不知道为什么这样做,有的甚至看不懂,真是博大精深!

基于原型的类继承

JavaScript 是基于原型的编程语言,原型用来区别类和实例。原型是一个“模板”对象,它上面的属性被用做初始化一个新对象。任何对象都可以作为另一个对象的原型对象,以此来共享属性。实际上,可以将其理解为某种形式的继承。

当读取一个对象的属性时,JavaScript 首先会在本地对象中查找这个属性,如果没有找到,JavaScript 开始在对象的原型中查找,若还未找到还会继续查找原型的原型,直到查找到Object.prototype。如果找到这个属性,则返回这个值,否则返回undefined。例如,给 Array.prototype 添加了属性,那么所有的 JavaScript 数组都具有了这些属性。

让子类继承父类的属性的方法:
先定义一个构造函数,然后将父类的新实例赋值给构造函数的原型:

// 父,动物大类
var Animal = function(){};
Animal.prototype.breath = function(){
    console.log('breath');
};

// 子,狗类
var Dog = function(){};

// Dog 继承了Animal
Dog.prototype = new Animal;
Dog.prototype.wag = function(){
    console.log('wag tail');
};

检查继承是否生效了:

var dog1 = new Dog;
dog1.wag();
dog1.breath(); // 继承的属性

给“类”库添加继承

通过传入一个可选的父类来创建新类,这个可以作为创建类的基础模板:

var Class = function(parent){
    var klass = function(){
        this.init.apply(this, arguments);
    };

    // 改变klass 的原型
    if (parent) {
        var subclass = function() { };
        subclass.prototype = parent.prototype;
        klass.prototype = new subclass;
    };

    klass.prototype.init = function(){};

    // 定义别名
    klass.fn = klass.prototype;
    klass.fn.parent = klass;
    klass._super = klass.__proto__;
    /* include/extend 相关的代码…… */

    return klass;
};

如果将parent 传入Class 构造函数,那么所有的子类则共享同一个原型。这种创建
临时匿名函数的小技巧避免了在继承类的时候创建实例,这里暗示了只有实例的属性才会被继承,而非类的属性【我没读懂这句和上面代码的关系,感觉已经晕了 = =】。设置对象的proto ;属性并不是所有浏览器都支持,类似Super.js的类库则通过属性复制的方式来解决这
个问题,而非通过固有的动态继承的方式来实现。

通过给Class 传入父类来实现简单的继承:

var Animal = new Class;
Animal.include({
    breath: function(){
        console.log('breath');
    }
});

var Cat = new Class(Animal);

// 用法
var tommy = new Cat;

函数调用

在JavaScript中,函数和其他东西一样都是对象。和其他对象不同的是,函数可调用。函数内上下文,如this 的取值,取决调用它的位置和方法。

除了使用方括号可以调用函数之外,还有其他两种方法可以调用函数:apply()call()。两者的区别在于传入函数的参数的形式。

apply() 函数有两个参数:第1个参数是上下文,第2个参数是参数组成的数组。如果上下文是null,则使用全局对象代替。例如:

function.apply(this, [1, 2, 3])

call()的第1个参数是上下文,后续是实际传入的参数序列:

function.call(this, 1, 2, 3);

JavaScript 中允许更换上下文是为了共享状态,尤其是在事件回调中。jQuery 在其API 的实现中就利用了apply() 和call() 来更改上下文,比如在事件处理程序中或者使用each() 来做迭代时。

$('.clicky').click(function(){
    // ‘this’指向当前节点
    $(this).hide();
});

$('p').each(function(){
    // ‘this’指向本次迭代
    $(this).remove();
});

为了访问原始上下文,可以将this 的值存入一个局部变量中,这是一种常见的模式,比如:

var clicky = {
    wasClicked: function(){
        /* ... */
    },

    addListeners: function(){
        var self = this;
        $('.clicky').click(function(){
            self.wasClicked()
        });
    }
};

clicky.addListeners();

可以用apply来将这段代码变得更干净一些,通过将回调包装在另外一个匿名函数中,来保持原始的上下文:

var proxy = function(func, thisObject){
    return(function(){
        return func.apply(thisObject, arguments);
    });
};

var clicky = {
    wasClicked: function(){
        /* ... */
    },
    addListeners: function(){
        var self = this;
        $('.clicky').click(proxy(this.wasClicked, this));
    }
};

上面的例子中在点击事件的回调中指定了要使用的上下文;jQuery中调用这个函数所用的上下文就可以忽略了。实际上jQuery也包含了实现了这个功能的API——jQuery.proxy()

$('.clicky').click($.proxy(function(){ /* ... */ }, this));

使用apply()call()还有其他很有用的原因,比如“委托”。可以将一个调用委托给另一个调用,甚至可以修改传入的参数:

var App {
    log: function(){
        if (typeof console == "undefined") return;

        // 将参数转换为合适的数组
        var args = jQuery.makeArray(arguments);

        // 插入一个新的参数
        args.unshift("(App)");

        // 委托给console
        console.log.apply(console, args);
    }
};

这个例子中首先构建了一个参数数组,然后将参数添加进去,最后将这个调用委托给了console.log()arguments变量是解释器内置的当前调用的作用域内用来保存参数的数组。但它并不是真正的数组,比如它是不可变的,因此需要通过jQuery.makeArray()将其转换为可用的数组。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
Sherwei Sherwei
2年前
JavaScript学习资源大全
在线文档类|名称及链接|特点|评分||||||现代JavaScript教程(https://zh.javascript.info/)|是React与MDN并列推荐的JavaScript学习教程,以最新的JavaSc
Stella981 Stella981
3年前
Python+Selenium自动化篇
本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子。0.元素定位方法主要有:id定位:find\_element\_by\_id('')name定位:find\_element\_by\_name('')class定位:find\_element\_by\_class\_name(''
Stella981 Stella981
3年前
Linux应急响应(四):盖茨木马
0x00前言Linux盖茨木马是一类有着丰富历史,隐藏手法巧妙,网络攻击行为显著的DDoS木马,主要恶意特点是具备了后门程序,DDoS攻击的能力,并且会替换常用的系统文件进行伪装。木马得名于其在变量函数的命名中,大量使用Gates这个单词。分析和清除盖茨木马的过程,可以发现有很多值得去学习和借鉴的地方。0x01应急场景
Stella981 Stella981
3年前
JavaScript 基于原型链的继承
JavaScript对象是动态的属性“包”(指其自己的属性)。JavaScript对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。遵循ECMAScript标准,someObject.Prototype
Stella981 Stella981
3年前
JavaScript面向对象编程的15种设计模式
在程序设计中有很多实用的设计模式,而其中大部分语言的实现都是基于“类”。在JavaScript中并没有类这种概念,面向对象编程不是基于类,而是基于原型去面向对象编程,JS中的函数属于一等对象,而基于JS中闭包与弱类型等特性,在实现一些设计模式的方式上与众不同。ps:本文之讲述面向对象编程的设计模式策略,JavaScript原型的基础请参考阮一峰面向
Stella981 Stella981
3年前
JavaScript——面向对象以及基于类的继承
!(http://static.oschina.net/uploads/img/201601/15103654_Y7EU.gif)!(http://static.oschina.net/uploads/img/201601/15103654_PyU6.gif)ViewCode1/
Stella981 Stella981
3年前
Javascript中,实现类与继承的方法和优缺点分析
Javascript是一种弱类型语言,不存在类的概念,但在js中可以模仿类似于JAVA中的类,实现类与继承第一种方法:利用Javascript中的原型链1//首先定义一个父类23functionAnimal(name,age){4//定义父类的属性5thi
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
4个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(