我是😈乖宝宝 bjsxt069
关注数: 2 粉丝数: 85 发帖数: 225 关注贴吧数: 8
我是如何走上Java这条路的 17年我毕业了,专业听着还不错,电子信息与技术,可惜是个破大专,而且我还是一个女生。 上学时,我就是个得过且过的差生,从来没为未来做过什么计划,大波轰的进了一家专门做手机软件测试的公司,每天重复着点点点的工作。实习期只有几百块的补贴,要知道,在北京这样一个国际化大都市,几百块,只够我合租床铺,天天吃泡面的。 工资刚到手,钱包就被信用卡吸的干干净净。月底不得不厚着脸皮接受家里的接济。难道15年书就这样白度了吗? 几个老同事聊起他们做开发或者白盒测试的,新来的实习生都有10K左右的月薪,还是15薪。他们正在考虑是不是要转行!转行?我仿佛看到了前进的方向。 于是我跟着几个老员工,相互督促着,利用闲暇时间自学。自学了几个月时间,我的毕业证也下来了,工资从几百的补助,也变成了3500,比程序员还有白盒依然有一道质的鸿沟。这时候我一边继续自学,一边去投简历去找工作。只要是有面试机会,我就会珍惜,但是每次给我的答复,都是一成不变的“回去等通知吧”。我知道HR只是礼貌性的拒接,所以我认真把每次面试不会的题目都记录下来,一一作了整整。 终于有公司肯要我了,虽然是一家外包公司,但是工资有了6.5K,而且是13薪。当我拿到offer时,都不知道怎么样才能表达出自己的喜悦。 转眼4年过去了,现在的我在一家不算大的公司。工作不是很累,偶尔加加班也有加班费,收入和那些996肯定是比不的,但是也高出北京平均工资一截了。年近30的我依然做着Java开发。不仅是我,之前的几个同事转行也都比较成功,一个比我大十来岁的同事,现在已经是项目经理了。 之前我们工作的那个单位后来倒闭了,挺感谢当时HR看错了专业(我们学校有计算机专业,但是电子信息被当时的人事看成了计算机专业),让我有机会接触到这个行业,这其中的艰辛是我这个学渣从前不曾敢想的。这几年IT行业发展迅速,想要在这里有所作为,只能依靠真凭实学了。通过这几年的自学和摸索,我也整理了一些学习心得,希望能帮助到想学习的同学。 1、万事开头难,刚开始自学,如果是自制力一般的小伙伴,可以选择一些相对完整的入门资料,对照视频自己多敲代码做练习。 2、有时间多去各大招聘网站,查看相关岗位要求,根据技术要求找项目做练习。 3、条件允许,可以试着投一些简历,先不要投大公司。增加自己的面试经验。 4、提升自己的英文水平,如果你只想做个普通码农,大概几百个常用单词就够了,但是你想有更好的发展,就需要较好的英语阅读能力了。 5、提高自己的团队协作能力,一个大的项目不是一个人可以完成的,所以要时刻注意代码规范。 6、提高自己的团队协调能力和应急处理能力,除非您想做一辈子码农。 7、当然,如果你有足够的精力,最好去学习一些关于计算机的硬件还有数学中的一些知识,有时别人几行代码,就可以顶你几十甚至更多行代码。
我是如何走上Java这条路的 17年我毕业了,专业听着还不错,电子信息与技术,可惜是个破大专,而且我还是一个女生。 上学时,我就是个得过且过的差生,从来没为未来做过什么计划,大波轰的进了一家专门做手机软件测试的公司,每天重复着点点点的工作。实习期只有几百块的补贴,要知道,在北京这样一个国际化大都市,几百块,只够我合租床铺,天天吃泡面的。 工资刚到手,钱包就被信用卡吸的干干净净。月底不得不厚着脸皮接受家里的接济。难道15年书就这样白度了吗? 几个老同事聊起他们做开发或者白盒测试的,新来的实习生都有10K左右的月薪,还是15薪。他们正在考虑是不是要转行!转行?我仿佛看到了前进的方向。 于是我跟着几个老员工,相互督促着,利用闲暇时间自学。自学了几个月时间,我的毕业证也下来了,工资从几百的补助,也变成了3500,比程序员还有白盒依然有一道质的鸿沟。这时候我一边继续自学,一边去投简历去找工作。只要是有面试机会,我就会珍惜,但是每次给我的答复,都是一成不变的“回去等通知吧”。我知道HR只是礼貌性的拒接,所以我认真把每次面试不会的题目都记录下来,一一作了整整。 终于有公司肯要我了,虽然是一家外包公司,但是工资有了6.5K,而且是13薪。当我拿到offer时,都不知道怎么样才能表达出自己的喜悦。 转眼4年过去了,现在的我在一家不算大的公司。工作不是很累,偶尔加加班也有加班费,收入和那些996肯定是比不的,但是也高出北京平均工资一截了。年近30的我依然做着Java开发。不仅是我,之前的几个同事转行也都比较成功,一个比我大十来岁的同事,现在已经是项目经理了。 之前我们工作的那个单位后来倒闭了,挺感谢当时HR看错了专业(我们学校有计算机专业,但是电子信息被当时的人事看成了计算机专业),让我有机会接触到这个行业,这其中的艰辛是我这个学渣从前不曾敢想的。这几年IT行业发展迅速,想要在这里有所作为,只能依靠真凭实学了。通过这几年的自学和摸索,我也整理了一些学习心得,希望能帮助到想学习的同学。 1、万事开头难,刚开始自学,如果是自制力一般的小伙伴,可以选择一些相对完整的入门资料,对照视频自己多敲代码做练习。 2、有时间多去各大招聘网站,查看相关岗位要求,根据技术要求找项目做练习。 3、条件允许,可以试着投一些简历,先不要投大公司。增加自己的面试经验。 4、提升自己的英文水平,如果你只想做个普通码农,大概几百个常用单词就够了,但是你想有更好的发展,就需要较好的英语阅读能力了。 5、提高自己的团队协作能力,一个大的项目不是一个人可以完成的,所以要时刻注意代码规范。 6、提高自己的团队协调能力和应急处理能力,除非您想做一辈子码农。 7、当然,如果你有足够的精力,最好去学习一些关于计算机的硬件还有数学中的一些知识,有时别人几行代码,就可以顶你几十甚至更多行代码。 ———————————————— JAVA从0到就业需要学习的全套视频:
入门java编程需要掌握的知识都有哪些 java编程开发随着互联网的不断发展而被众多程序员所掌握,无论是java编程应用还是java程序员的数量都是非常多的,而今天我们就给大家简单分享一些入门java编程需要掌握的知识都有哪些。 1、数据类型 Java有2种数据类型,一种是基本数据类型,一种是引用类型。 基本数据类型用于存储简单类型的数据,比如说,int、long、byte、short用于存储整数,float、double用于存储浮点数,char用于存储字符,boolean用于存储布尔值。 2、声明变量 要声明一个变量,必须指定它的名字和类型,count和name在声明后会得到一个默认值,按照它们的数据类型——不能是局部变量(否则Java编译器会在你使用变量的时候提醒要先赋值),必须是类成员变量。 3、数组 数组在Java中占据着重要的位置,它是很多集合类的底层实现。数组属于引用类型,它用来存储一系列指定类型的数据。 4、关键字 关键字属于保留字,在Java中具有特殊的含义,比如说public、final、static、new等等,它们不能用来作为变量名。 5、程序结构 Java中小的程序单元叫做类,一个类可以有一个或者多个字段(也叫作成员变量),还可以有一个或者多个方法,甚至还可以有一些内部类。 如果一个类想要执行,就必须有一个main方法——程序运行的入口,就好像人的嘴一样,嗯,可以这么牵强的理解一下。 6、编译然后执行代码 通常,一些教程在介绍这块内容的时候,建议你通过命令行中先执行javac命令将源代码编译成字节码文件,然后再执行java命令指定代码。
Python是什么?Python能干什么?为什么这么火? Python简介 Python是一个通用目的编程语言。Python已经发展了很多年: Python 的创造者Guido van Rossum从1990年就开始了Python 的开发。这个稳定而成熟的语言是非常高层的、动态的、面向对象的和跨平台的,所有这些特征都非常吸引开发者。 Python 可以在所有主流的硬件平台和操作系统上运行,因此Python不会限制开发者的平台选择。Python为软件的生命周期的每个阶段都提供了非常高的效率:分析、设计、原型、编码、测试、调试、优化、文档、部署和维护。几年来,Python 的流行已经8渐稳定,并且在不间断地增长。如今,熟悉Python 对于每个程序员来说都是一种优势,因为Python已经渗透到了每- -种开发环境中, 并且Python具有一些非常有用的功能,可以作为任何一-种软件解决方案的一部分。 Python提供了一种非常独特的功能,可以将优雅、简单、实用性和强大功能融合在一起。使用Python,开发者可以快速提高开发效率,这要感谢Python提供的一致性和规律性、丰富的标准库,以及许多可以很容易在Python中使用的第三方模块。 Python 是很容易学习的,因此,如果读者刚开始学习编写程序,非常适合于从学习Python 开始,与此同时,对于大多数非常有经验的专家而言。Python 的功能也是足够强大的。人与能量效率图 Python到底有多火? Python作为当下最热门的编程语言,在2018年世界脚本语言排行榜中位列榜首,已经成为了多个领域的首选语言。能用到Python 的地方非常多。从入门级小白到专业级的大佬,数据挖掘、科学计算、图像处理、人工智能,Python 都可以胜任。或许是因为这种万能属性,现在有很多的小伙伴都开始学习 Python。 而现在 Python 的火爆甚至已经来到了程序员的圈子外,进入了国务院《新一代人工智能发展规划的通知》里。 Python 也已经走进了小学生的课程里,其实不只是小学生,为了自己的发展前景,或许你才是最该学 Python 的人。 Python都被用在哪儿? 自Python由Guido van Rossum于1989年底发明创建以来,基于此项技术的网站和软件项目已经有了数千个。Python 由于其独特性,使其在各种编程语言中脱颖而出,在全世界拥有大量拥护它的程序员。 Python 的优点是什么? 简单、免费、兼容性、面向对象、 函数库 在哪里使用 Python 语言? 爬虫 Web 程序开发 桌面程序开发 科学计算 图像处理 人工智能 等以及其他的各种各样的方向Python 都可以胜任。 对于一些从未来没有写过代码的人来说,Python 的代码简洁易懂。 也正是因为这个原因,与其他语言相比,python对小白更友好。 还有就是 Python 编写的程序其可维护性很高,从商业角度来看,这也可以很大程度上在降低开发成本的同时提高程序员的生产力。
大数据基础学习:Linux操作系统是什么,操作系统概述,学习方法 好的开始是成功的一半。学习 Linux 的第一个问题是搞明白 Linux 是什么,了解其来龙去脉、前世今生,知道其发展趋势、应用前景,弄清楚为什么学习它,以及如何掌握它和使用它,知其然更要知其所以然。学习更多大数据知识,请参考北京尚学堂。 本章致力于让读者对 Linux 有一个宏观的认识,总览其整体,后续章节再依次讲解 Linux 的每一部分的知识点。 工欲善其事,必先利其器。建议学习 Linux 的朋友不要忽视本章章。很多人看技术类图书都不喜欢或不重视第一章,甚至直接跳过去,觉得大多是介绍性的内容,陈词滥调、形式化,且没什么 技术含量。 一方面,更多地了解 Linux 相关知识对后续阅读本教程助益良多,避免后续学习时盲人摸象;另一方面,本书第一章与其他书籍有所不同,它结合了笔者的学习和工作经历,给出了很多指导,可供读者参考。 计算机是一台机器,它按照用户的要求接收信息、存储数据、处理数据,然后再将处理结果输出(文字、图片、音频、视频等)。计算机由硬件和软件组成: 硬件是计算机赖以工作的实体,包括显示器、键盘、鼠标、硬盘、CPU、主板等; 软件会按照用户的要求协调整台计算机的工作,比如 Windows、Linux、Mac OS、Android 等操作系统,以及 Office、QQ、迅雷、微信等应用程序。 Linux操作系统是什么,操作系统概述 操作系统(Operating System,OS)是软件的一部分,它是硬件基础上的第一层软件,是硬件和其它软件沟通的桥梁(或者说接口、中间人、中介等)。 操作系统会控制其他程序运行,管理系统资源,提供最基本的计算功能,如管理及配置内存、决定系统资源供需的优先次序等,同时还提供一些基本的服务程序,例如: 1) 文件系统 提供计算机存储信息的结构,信息存储在文件中,文件主要存储在计算机的内部硬盘里,在目录的分层结构中组织文件。文件系统为操作系统提供了组织管理数据的方式。 2) 设备驱动程序 提供连接计算机的每个硬件设备的接口,设备驱动器使程序能够写入设备,而不需要了解执行每个硬件的细节。简单来说,就是让你能吃到鸡蛋,但不用养一只鸡。 3) 用户接口 操作系统需要为用户提供一种运行程序和访问文件系统的方法。如常用的 Windows 图形界面,可以理解为一种用户与操作系统交互的方式;智能手机的 Android 或 iOS 系统,也是一种操作系统的交互方式。 4) 系统服务程序 当计算机启动时,会自启动许多系统服务程序,执行安装文件系统、启动网络服务、运行预定任务等操作。 打个比方,操作系统就好像是一个政府,其它软件都会被它管控;操作系统在给其他软件提供各种便利的同时,还会约束其他软件不能为所欲为。目前流行的服务器和 PC 端操作系统有 Linux、Windows、UNIX 等,手机操作系统有 Android、iOS、Windows Phone(简称 WP),嵌入式操作系统有 Windows CE、PalmOS、eCos、uClinux 等。 这主要讲解 Linux 这种操作系统的应用,并不想过多涉及操作系统的类型和功能等理论性的知识,本节的目的是让读者明白,操作系统也是软件的一种,只不过它是位于硬件和应用程序之间的底层的软件,它除了会为应用程序保驾护航,还会“杀死”不听话的应用程序,具有双面性。 Linux是学习大数据的基础,以上对操作系统的认知虽然只是“皮毛”,但它足以让我们学习 Linux 了。
web前端—面试题汇总(266-270)266、MVVM模式 web前端—面试题汇总(266-270) 266、MVVM模式的理解 MVVM 是 Model-View-ViewModel 的缩写。 Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。 View代表UI 组件,它负责将数据模型转化成UI 展现出来。 ViewModel监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。 ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。 267、VUE双向绑定原理 mvvm 双向绑定,采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter、getter,在数据变动时发布消息给订阅者,触发相应的监听回调。 要点: 实现一个数据监听器 Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者 实现一个指令解析器 Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数 实现一个 Watcher,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图 mvvm 入口函数,整合以上三者 具体步骤: 需要 observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter compile 解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图 Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,待属性变动 dep.notice() 通知时,调用自身的 update() 方法,并触发Compile 中绑定的回调。 268、生命周期 beforeCreate 在数据观测和初始化事件还未开始,VUE实例的挂载元素$el和数据对象都为undefined 可以进行的事件:加loading事件 created 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来 可以进行的事件:结束loading,请求数据为mounted作准备 beforeMount 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。($el和data都已经初始化,但仍是虚拟DOM节点) Mounted $el被新创建的vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。(VUE实例挂载完成,data.filter成功渲染) 可以进行的事件:配合路由钩子使用 beforeUpdate 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。 Update 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。 beforeDestroy 在实例销毁之前调用。实例仍然完全可用。 destroyed 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。 269、v-model 语法糖 v-bind="message" @input="message=$event.target.value" v-model利用的是 http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2FObject.defineProperty&urlrefer=b07998d51982318760178d40a57ce487 方法 http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2FObject.defineProperty&urlrefer=b07998d51982318760178d40a57ce487 (要添加或修改属性的对象, …属性名, 特征对象) 在添加属性是可以设置属性以下的特性: 1.是否只读 2.是否可删除 3.是否可遍历 4.可以为属性注册像改变事件一样的函数 代码示例 let nameValue = '' let obj = {} Object.defineProperty(obj, 'name', { set(value){ console.log('属性被赋值') nameValue = value }, get(){ console.log('属性被获取值') return nameValue } }) 270、VUE初始化闪动 根元素加上 style="display:none;" :style="{display:block;}" 利用v-clock [v-clock]{ display:none; }
微信小程序在app.js修改后的全局变量值在其他页面异步获取 微信小程序在app.js修改后的全局变量值在其他页面异步获取的问题 虽然app.js先于index.js。但是修改app.js中的全局变量是异步请求,如果你想在index.js里获取app.js修改后的值,那么需要使用promise来实现异步。 小程序默认项目自带了一种获取授权头像的信息了promise实现异步操作同步显示流程 http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fapp.js&urlrefer=3f75c40f89dfa9893bad8d06dc79e43f App({ //获取授权的头像信息 检测授权 getUserInfo() { return new Promise((resolve, reject) => { // 获取用户信息 wx.getSetting({ success: res => { if (res.authSetting['scope.userInfo']) { wx.getUserInfo({ success: res => { // 可以将 res 发送给后台解码出 unionId = resolve(this.globalData.userInfo); // 这里是关键 } }) }else{ //之前没有授权信息头像 reject(this.globalData.userInfo) wx.redirectTo({ url: '/pages/about/about' }) console.log("未授权"); } } }) }) }, globalData: { userInfo: null }})const app = getApp()Page({ data: { userInfo: {}, hasUserInfo: false, }, onLoad: function () { //检测授权信息 app.getUserInfo().then(res=>{ console.log(res); this.setData({ hasUserInfo:true, userInfo:res }) }) }, getUserInfo: function(e) { console.log(e) = this.setData({ userInfo: e.detail.userInfo, hasUserInfo: true }) }})<view class="container"> <view class="userinfo"> <button wx:if="{{!hasUserInfo}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 <^tton> <block wx:else> <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image> <text class="userinfo-nickname">{{userInfo.nickName}}</text> <ock> <7iew><7iew>
web前端—面试题汇总(261-265) 261、介绍js基本数据类型 1)ECMAScript中有5种基本数据类型: Undefined、Null、Boolean、Number和String 1种复杂的数据类型—Object,Object本质上是由一组无序的名值对组成的 其中Undefined、Null、Boolean、Number都属于基本类型。Object、Array和Function则属于引用类型,String有些特殊 2)变量 ES6前声明变量只有:var function ES6声明变量有:const---声明基本类型的常量变量值不能修改,引用类型的常量内部值可以修改只是保证地址一样就可以了 let Symbol 3)typeof操作---可以检测基本数据类型,返回字符串 var a console.log(typeof a); //'undefined' a = 1 console.log(typeof a); //'number' a = 'aa' console.log(typeof a); //'string' a = true console.log(typeof a); //'boolean' a = null console.log(typeof a); //'object' a = [] console.log(typeof a); //'object' a = {} console.log(typeof a); //'object' Boolean()函数的转换 262、编写一个方法,判断字符串是否是这样组成的,第一个必须为数字,最后一个必须为 字母 // \S---匹配任何非空白字符 \s匹配任何空白字符 var c = /^[0-9][\s|\S]*[a-zA-Z]$/; var str = '122' console.log(c.test(str)); // true 正则表达式——判断字符串组成,第一个必须是字母,后面可以是字母、数字、下划线,总长度为5-20 //判断字符串是否是这样组成的,第一个必须是字母,后面可以是字母、数字、下划线,总长度为5-20 var c = /^[a-zA-Z]\w{4,19}$/; // /是转义 ^ 是开头 [a-zA-Z]是字母出现一次 \w是任意字符 {4,11}是长度 $ 是结束 var str = 'ss4442' console.log(c.test(str)); // true 263、如何隐藏一个dom元素 css中隐藏DOM元素常见的5种方法 opacity:0 //将透明度设置为0,透明度为0的元素任然占据页面空间,响应用户交互 visibility:hidden //将元素隐藏,被隐藏的元素任然占据页面空间,不响应用户交互 diaplay:none //被隐藏的元素不在占据页面空间,不响应用户交互,相当于该元素不存在 position:absolute //通过top/right/bottom/left的值将元素移到页面不可见的地方 clip-path:polygon(0px,0px,0px,0px,0px,0px,0px,0px) //通过裁剪的方式 264、如何添加HTML事件,有几种方法?(至少两种方式) 在JavaScript中,有三种常用的绑定事件的方法: (1)在DOM元素中直接绑定 //原生函数 <input onclick="alert('谢谢支持')" type="button" value="点击我,弹出警告框" /> //自定义函数 <input onclick="myAlert()" type="button" value="点击我,弹出警告框" /> <script type="text/javascript"> function myAlert(){ alert("谢谢支持"); } </script> (2)在JavaScript代码中绑定---JavaScript代码与HTML标签分离,文档结构清晰,便于管理和开发 <input id="demo" type="button" value="点击我,显示 type 属性" /> <script type="text/javascript"> document.getElementById("demo").onclick=function(){ alert(this.getAttribute("type")); // this 指当前发生事件的HTML元素,这里是<div>标签 } </script> (3)绑定事件监听函数 function addEvent(obj,type,handle){ try{ // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本 obj.addEventListener(type,handle); }catch(e){ try{ // IE8.0及其以下版本 obj.attachEvent('on' + type,handle); }catch(e){ // 早期浏览器 obj['on' + type] = handle; } } } 265、前端常规开发优化策略(至少两种方式)(也就是性能优化的方法) (1) 减少http请求次数:css spirit,jsć的合并,使用缓存--本地缓存、cookie (2) JS,CSS源码压缩 (3) 用变量保存DOM节点查找的结果,减少DOM操作次数,优化javascript性能 (4)用setTimeout来避免页面失去响应 (5) 用hash-table来优化查找 (6) 当需要设置的样式很多时,设置className而不是直接操作style (7)少用全局变量 (8)缓存DOM (9)避免使用CSS Expression(计算频繁) (10) 图片预加载 (11) 避免在页面的主体布局中使用table,table要等其中的内容完全下载之后才会显示出来,显示比div css布局慢
web前端—面试题汇总(256-260)256、关于平衡二叉 web前端—面试题汇总(256-260) 256、关于平衡二叉树 平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,同时,平衡二叉树必定是二叉搜索树,反之则不一定。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。 257、使用css实现一个三角形 利用border去画~ 先看一下border的布局,如图: 所以三角形: 1.设置宽度、高度为0 2.不设置border-top 3.设置左右border颜色为transparent–透明 258、用promise手写ajax 259、手写一个类的继承,并解释一下继承的形式有很多中,js高程里面归纳了其中,我简单说一下前三种。 1.原型继承 2.构造函数继承 3.组合继承260、解释一下call函数和apply函数的作用,以及用法改变this的指向。 this的指向问题,在你不知道的js这本书中(神书)做了四点归纳: 1.默认绑定 (指 直接调用 foo(), this指向window) 2.隐式绑定(obj.foo(), this指向obj 这里会出现很多坑,下面的问题应该会有解答) 3.显示绑定(利用call、apply、bind改变this) 4.new(var cat = new Animal() , this指向cat对象)
web前端—面试题汇总(246-250)246、基本的数据类 web前端—面试题汇总(246-250) 246、基本的数据类型Java Script中的数据类型分为6种,两类:简单数据类型和复杂数据类型,简单数据类型包括 Number、Undefined、Null、Boolean 和String,复杂数据类型是Object。一、NumberNumber数据类型指的是数字,包括整型和浮点型。 示例 var x = 314; //十进制整var y = 070; //八进制,56var z = 0xA; //十六进制,10var w = 3.14; //浮点型(数值中必须包含一个小数点,并且小数点后面至少有一位数字)NaN (Not a Number)表示非数值数据,属于Number 类型,常用于一个本来要返回数值的操作数未返回数值; 特点1:任何涉及NaN的操作都会返回NaN; 特点2:NaN与任何值都不相等,包括NaN本身;二、String 类型String类型用于表示由零或多个16位Unicode字符组成的字符序列,即字符串。字符串可以由双引号(“)或单引号(‘)表示。 示例 var test ="小猪佩奇";var test = null;var test = undefined;三、Boolean 类型Boolean 类型有两个值,true 和 false。 注意:true 不一定等于1,false 不一定等于0; 四、Null类型Null类型是一个只有一个值的数据类型,即特殊的值null。代表一个空对象引用。 我们在定义一个变量时常初始化为null,当检查null 值的时候就知道是否已经为该变量赋过值了。 示例 var test = null;if(test != null){ alter("test对象已存在");}五、Undefined 类型Undefined类型只有一个值,即特殊的undefined。在使用var声明变量,但没有对其初始化时,这个变量的值就是undefined。 示例 var test;六、Object 类型js中对象是一组属性与方法的集合。我们看到的大多数类型值都是Object类型的实例。 示例 //1、使用new操作符创建示例var student = new Object();http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fstudent.name&urlrefer=24c538d83b6aa1b6d249e1ec180a3eba = 'tracy';http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fstudent.age&urlrefer=ddbd713f10bcfbe8d89cce94bcfee5d8 = 18;//2、使用对象字面量表示法var student = { name: 'tracy', age:18};247、基本的两列自适应布局左定右适应: 248、unix中常用的命令行虽然上过linux课,但是命令忘得差不多了 尴尬。。。249、OSI模型,HTTP,TCP,UDP分别在哪些层这个可以参考我另一个博客: http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fblog.csdn.net%2Fqq_22944825%2Farticle%2Fdetails%2F78160659&urlrefer=6657ad00c6746e475a4c7189bbc76eb2 OSI:物理层-数据链路层-网络层-传输层-会话层-表现层-应用层 250、手写一个jQuery插件1、$.extend(src)   该方法就是将src合并到jquery的全局对象中去,如: $.extend({ hello:function(){alert('hello');} });2、$.fn.extend(src)   该方法将src合并到jquery的实例对象中去,如: $.fn.extend({ hello:function(){alert('hello');} });
web前端—面试题汇总(241-245)241、为什么要初始 web前端—面试题汇总(241-245) 241、为什么要初始化CSS样式?   答案:因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。   当然,初始化样式会对SEO有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化。 242、浮动元素引起的问题?   答案:a. 父元素的高度无法被撑开,影响与父元素同级的元素   b. 与浮动元素同级的非浮动元素会跟随其后   c. 若非第一个元素浮动,则该元素之前的元素也需要浮动,否则会影响页面显示的结构 243、line-height三种赋值方式有何区别?(带单位、纯数字、百分比)?   答案:带单位:px不用计算,em则会使元素以其父元素font-size值为参考来计算自己的行高   纯数字:把比例传递给后代,例如父级行高为1.5,子元素字体为18px,则子元素行高为1.5*18=27px   百分比:将计算后的值传递给后代 244、link、:visited、:hover、:active的执行顺序是怎么样的?   答案:L-V-H-A,l(link)ov(visited)e h(hover)a(active)te,即用喜欢和讨厌两个词来概括 245、css属性content有什么作用?有什么应用?   答案:css的content属性专门应用在 before/after 伪元素上,用于来插入生成内容,可以配合自定义字体显示特殊符号。
web前端—面试题汇总(236-240) 236、position的absolute与fixed共同点与不同点<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;">A:共同点:<span class="hljs-number" style="color: rgb(42, 161, 152);">1.</span>改变行内元素的呈现方式,display被置为block;<span class="hljs-number" style="color: rgb(42, 161, 152);">2.</span>让元素脱离普通流,不占据空间;<span class="hljs-number" style="color: rgb(42, 161, 152);">3.</span>默认会覆盖到非定位元素上B不同点:absolute的”根元素“是可以设置的,而<span class="hljs-keyword" style="color: rgb(133, 153, 0);">fixed</span>的”根元素“固定为浏览器窗口。当你滚动网页,<span class="hljs-keyword" style="color: rgb(133, 153, 0);">fixed</span>元素与浏览器窗口之间的距离是不变的。 </code>237、介绍一下CSS的盒子模型?<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;">1)有两种, IE 盒子模型、标准 W3C 盒子模型;IE的content部分包含了 border 和 pading;2)盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border).</code>238、CSS 选择符有哪些?哪些属性可以继承?优先级算法如何计算? CSS3新增伪类有那些?<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;"> * 1<span class="hljs-class" style="color: rgb(155, 112, 63);">.id</span>选择器( # <span class="hljs-tag" style="color: rgb(133, 153, 0);">myid</span>) 2.类选择器(<span class="hljs-class" style="color: rgb(155, 112, 63);">.myclassname</span>) 3.标签选择器(<span class="hljs-tag" style="color: rgb(133, 153, 0);">div</span>, <span class="hljs-tag" style="color: rgb(133, 153, 0);">h1</span>, <span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span>) 4.相邻选择器(<span class="hljs-tag" style="color: rgb(133, 153, 0);">h1</span> + <span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span>) 5.子选择器(<span class="hljs-tag" style="color: rgb(133, 153, 0);">ul</span> > <span class="hljs-tag" style="color: rgb(133, 153, 0);">li</span>) 6.后代选择器(<span class="hljs-tag" style="color: rgb(133, 153, 0);">li</span> <span class="hljs-tag" style="color: rgb(133, 153, 0);">a</span>) 7.通配符选择器( * ) 8.属性选择器(<span class="hljs-tag" style="color: rgb(133, 153, 0);">a</span><span class="hljs-attr_selector" style="color: rgb(203, 75, 22);">[rel = "external"]</span>) 9.伪类选择器(<span class="hljs-tag" style="color: rgb(133, 153, 0);">a</span>: <span class="hljs-tag" style="color: rgb(133, 153, 0);">hover</span>, <span class="hljs-tag" style="color: rgb(133, 153, 0);">li</span><span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:nth-child</span>) * 可继承的样式: <span class="hljs-tag" style="color: rgb(133, 153, 0);">font-size</span> <span class="hljs-tag" style="color: rgb(133, 153, 0);">font-family</span> <span class="hljs-tag" style="color: rgb(133, 153, 0);">color</span>, <span class="hljs-tag" style="color: rgb(133, 153, 0);">text-indent</span>; * 不可继承的样式:<span class="hljs-tag" style="color: rgb(133, 153, 0);">border</span> <span class="hljs-tag" style="color: rgb(133, 153, 0);">padding</span> <span class="hljs-tag" style="color: rgb(133, 153, 0);">margin</span> <span class="hljs-tag" style="color: rgb(133, 153, 0);">width</span> <span class="hljs-tag" style="color: rgb(133, 153, 0);">height</span> ; * 优先级就近原则,同权重情况下样式定义最近者为准; * 载入样式以最后载入的定位为准; 优先级为: !<span class="hljs-tag" style="color: rgb(133, 153, 0);">important</span> > <span class="hljs-tag" style="color: rgb(133, 153, 0);">id</span> > <span class="hljs-tag" style="color: rgb(133, 153, 0);">class</span> > <span class="hljs-tag" style="color: rgb(133, 153, 0);">tag</span> <span class="hljs-tag" style="color: rgb(133, 153, 0);">important</span> 比 内联优先级高,但内联比 <span class="hljs-tag" style="color: rgb(133, 153, 0);">id</span> 要高 <span class="hljs-tag" style="color: rgb(133, 153, 0);">CSS3</span>新增伪类举例: <span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span><span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:first-of-type</span> 选择属于其父元素的首个 <<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span>> 元素的每个 <<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span>> 元素。<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span><span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:last-of-type</span> 选择属于其父元素的最后 <<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span>> 元素的每个 <<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span>> 元素。<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span><span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:only-of-type</span> 选择属于其父元素唯一的 <<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span>> 元素的每个 <<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span>> 元素。<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span><span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:only-child</span> 选择属于其父元素的唯一子元素的每个 <<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span>> 元素。<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span><span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:nth-child(2)</span> 选择属于其父元素的第二个子元素的每个 <<span class="hljs-tag" style="color: rgb(133, 153, 0);">p</span>> 元素。<span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:enabled</span> <span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:disabled</span> 控制表单控件的禁用状态。<span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:checked</span> 单选框或复选框被选中。</code>239、列出display的值,说明他们的作用。position的值, relative和absolute分别是相对于谁进行定位的?<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;"><span class="hljs-number" style="color: rgb(42, 161, 152);">1.</span> block 象块类型元素一样显示。 <span class="hljs-keyword" style="color: rgb(133, 153, 0);">inline</span> 缺省值。象行内元素类型一样显示。 <span class="hljs-keyword" style="color: rgb(133, 153, 0);">inline</span>-block 象行内元素一样显示,但其内容象块类型元素一样显示。 <span class="hljs-built_in" style="color: rgb(38, 139, 210);">list</span>-item 象块类型元素一样显示,并添加样式列表标记。 <span class="hljs-number" style="color: rgb(42, 161, 152);">2.</span> *absolute 生成绝对定位的元素,相对于 <span class="hljs-keyword" style="color: rgb(133, 153, 0);">static</span> 定位以外的第一个祖先元素进行定位。 *fixed (老IE不支持) 生成绝对定位的元素,相对于浏览器窗口进行定位。 *relative 生成相对定位的元素,相对于其在普通流中的位置进行定位。 * <span class="hljs-keyword" style="color: rgb(133, 153, 0);">static</span> 默认值。没有定位,元素出现在正常的流中 *(忽略 top, bottom, left, right z-index 声明)。 * inherit 规定从父元素继承 position 属性的值。</code>240、CSS3有哪些新特性?<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;"><span class="hljs-constant" style="color: rgb(181, 137, 0);">CSS3</span>实现圆角(border-radius),阴影(box-shadow),对文字加特效(text-shadow、),线性渐变(gradient),旋转(transform)<span class="hljs-symbol" style="color: rgb(203, 75, 22);">transform:</span>rotate(<span class="hljs-number" style="color: rgb(42, 161, 152);">9</span>deg) scale(<span class="hljs-number" style="color: rgb(42, 161, 152);">0</span>.<span class="hljs-number" style="color: rgb(42, 161, 152);">85</span>,<span class="hljs-number" style="color: rgb(42, 161, 152);">0</span>.<span class="hljs-number" style="color: rgb(42, 161, 152);">90</span>) translate(0px,-<span class="hljs-number" style="color: rgb(42, 161, 152);">30</span>px) skew(-<span class="hljs-number" style="color: rgb(42, 161, 152);">9</span>deg,0deg);<span class="hljs-regexp" style="color: rgb(42, 161, 152);">//</span>旋转,缩放,定位,倾斜增加了更多的<span class="hljs-constant" style="color: rgb(181, 137, 0);">CSS</span>选择器 多背景 rgba 在<span class="hljs-constant" style="color: rgb(181, 137, 0);">CSS3</span>中唯一引入的伪元素是<span class="hljs-symbol" style="color: rgb(203, 75, 22);">:</span><span class="hljs-symbol" style="color: rgb(203, 75, 22);">:selection</span>.媒体查询,多栏布局border-image</code>
web前端—面试题汇总(231-235)231、请你谈谈Co web前端—面试题汇总(231-235) 231、请你谈谈Cookie的弊端 cookie虽然在持久保存客户端数据提供了方便,分担了服务器存储的负担,但还是有很多局限性的。 第一:每个特定的域名下最多生成20个cookie <code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;"><span class="hljs-number" style="color: rgb(42, 161, 152);">1.</span>IE6或更低版本最多<span class="hljs-number" style="color: rgb(42, 161, 152);">20</span>个cookie <span class="hljs-number" style="color: rgb(42, 161, 152);">2.</span>IE7和之后的版本最后可以有<span class="hljs-number" style="color: rgb(42, 161, 152);">50</span>个cookie。 <span class="hljs-number" style="color: rgb(42, 161, 152);">3.F</span>irefox最多<span class="hljs-number" style="color: rgb(42, 161, 152);">50</span>个cookie <span class="hljs-number" style="color: rgb(42, 161, 152);">4.</span>chrome和Safari没有做硬性限制 </code> IE和Opera 会清理近期最少使用的cookie,Firefox会随机清理cookie。 cookie的最大大约为4096字节,为了兼容性,一般不能超过4095字节。 IE 提供了一种存储可以持久化用户数据,叫做uerData,从IE5.0就开始支持。每个数据最多128K,每个域名下最多1M。这个持久化数据放在缓存中,如果缓存没有清理,那么会一直存在。 优点:极高的扩展性和可用性 <code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;"> 1.通过良好的编程,控制保存在cookie中的session对象的大小。 2.通过加密和安全传输技术(SSL),减少cookie被破解的可能性。 3.只在cookie中存放不敏感数据,即使被盗也不会有重大损失。 4.控制cookie的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的cookie。 </code> 缺点: <code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;"><span class="hljs-number" style="color: rgb(42, 161, 152);">1.</span>`<span class="javascript">Cookie</span>`数量和长度的限制。每个domain最多只能有<span class="hljs-number" style="color: rgb(42, 161, 152);">20</span>条cookie,每个cookie长度不能超过<span class="hljs-number" style="color: rgb(42, 161, 152);">4</span>KB,否则会被截掉。 <span class="hljs-number" style="color: rgb(42, 161, 152);">2.</span>安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。 <span class="hljs-number" style="color: rgb(42, 161, 152);">3.</span>有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。 </code> 232、浏览器本地存储 在较高版本的浏览器中,js提供了sessionStorage和globalStorage。在HTML5中提供了localStorage来取代globalStorage。 html5中的Web Storage包括了两种存储方式:sessionStorage和localStorage。 sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。 而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。 233、web storage和cookie的区别 Web Storage的概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。 除此之外,Web Storage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie。 但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生 浏览器的支持除了IE7及以下不支持外,其他标准浏览器都完全支持(ie及FF需在web服务器里运行),值得一提的是IE总是办好事,例如IE7、IE6中的UserData其实就是javascript本地存储的解决方案。通过简单的代码封装可以统一到所有的浏览器都支持web storage。 localStorage和sessionStorage都具有相同的操作方法,例如setItem、getItem和removeItem等 234、display:none和visibility:hidden的区别? <code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;"><span class="hljs-tag" style="color: rgb(133, 153, 0);">display</span><span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:none</span> 隐藏对应的元素,在文档布局中不再给它分配空间,它各边的元素会合拢, 就当他从来不存在。 <span class="hljs-tag" style="color: rgb(133, 153, 0);">visibility</span><span class="hljs-pseudo" style="color: rgb(203, 75, 22);">:hidden</span> 隐藏对应的元素,但是在文档布局中仍保留原来的空间。 </code> 235、CSS中 link 和@import 的区别是? <code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;">A:(<span class="hljs-number" style="color: rgb(42, 161, 152);">1</span>) <span class="hljs-keyword" style="color: rgb(133, 153, 0);">link</span>属于HTML标签,而<span class="hljs-variable" style="color: rgb(181, 137, 0);">@import</span>是CSS提供的; (<span class="hljs-number" style="color: rgb(42, 161, 152);">2</span>) 页面被加载的时,<span class="hljs-keyword" style="color: rgb(133, 153, 0);">link</span>会同时被加载,而<span class="hljs-variable" style="color: rgb(181, 137, 0);">@import</span>引用的CSS会等到页面被加载完再加载;(<span class="hljs-number" style="color: rgb(42, 161, 152);">3</span>) import只在IE5以上才能识别,而<span class="hljs-keyword" style="color: rgb(133, 153, 0);">link</span>是HTML标签,无兼容问题; (<span class="hljs-number" style="color: rgb(42, 161, 152);">4</span>) <span class="hljs-keyword" style="color: rgb(133, 153, 0);">link</span>方式的样式的权重 高于<span class="hljs-variable" style="color: rgb(181, 137, 0);">@import</span>的权重. </code>
web前端—面试题汇总(226-230)226、简述Vue的 web前端—面试题汇总(226-230) 226、简述Vue的响应式原理当一个Vue实例创建时,vue会遍历data选项的属性,用 http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2FObject.defineProperty&urlrefer=b07998d51982318760178d40a57ce487 将它们转为 gettertter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。 227、简述Vue的生命周期 它可以总共分为8个阶段: beforeCreate(创建前), created(创建后), beforeMount(载入前), mounted(载入后), beforeUpdate(更新前), updated(更新后), beforeDestroy(销毁前), destroyed(销毁后) 228、vue中Computed 和 Watch的使用和区别 1、计算属性computed适用的情形 我们可能会有这样的需求,一个数据属性在它所依赖的属性发生变化时,也要发生变化,这种情况下,我们最好使用计算属性。 例如在下面这个例子中,如果我们使用监听函数,代码就会变得有点冗余。 2、监听器watch适当的情形 watch函数适用于,当数据发生变化时,执行异步操作或较大开销操作的情况。 229、vue 与 react优缺点对比 vue API设计上简单,语法简单,学习成本低 构建方面不包含路由和ajax功能,使用vuex, vue-router 指令(dom)和组件(视图,数据,逻辑)处理清晰 性能好,容易优化 基于依赖追踪的观察系统,并且异步队列更新 独立触发 v-model 实时渲染 适用于:模板和渲染函数的弹性选择 简单的语法及项目搭建 更快的渲染速度和更小的体积 react 利用jsx创建虚拟dom 是一种在内存中描述dom数状态的数据结构 函数式的方法描述视图 使用虚拟dom作为模板 程序片段 不好控制dom 生命周期 服务端渲染:react的虚拟dom的生成可以在任何支持js的环境生成的,所以可以在node环境生成,直接转为string,然后插入到html文件中输出浏览器便可 适用于:大型应用和更好的可测试性;同时适用于web端和原生app;更大的生态圈 优点 React伟大之处就在于,提出了Virtual Dom这种新颖的思路,并且这种思路衍生出了React Native,有可能会统一Web/Native开发。在性能方面,由于运用了Virtual Dom技术,Reactjs只在调用setState的时候会更新dom,而且还是先更新Virtual Dom,然后和实际Dom比较,最后再更新实际Dom。这个过程比起Angularjs的bind方式来说,一是更新dom的次数少,二是更新dom的内容少,速度肯定快 ReactJS更关注UI的组件化,和数据的单向更新,提出了FLUX架构的新概念,现在React可以直接用Js ES6语法了,然后通过webpack编译成浏览器兼容的ES5,开发效率上有些优势. React Native生成的App不是运行在WebView上,而是系统原生的UI,React通过jsx生成系统原生的UI,iOS和Android的React UI组件还是比较相似的,大量代码可以复用 维护UI的状态,Angular 里面使用的是 $scope,在 React 里面使用的是 this.setState。 而 React 的好处在于,它更简单直观。所有的状态改变都只有唯一一个入口 this.setState(), 同构的JavaScript 单页面JS应用程序的最大缺陷在于对搜索引擎的索引有很大限制。React对此有了解决方案。 React可以在服务器上预渲染应用再发送到客户端。它可以从预渲染的静态内容中恢复一样的记录到动态应用程序中。 因为搜索引擎的爬虫程序依赖的是服务端响应而不是JavaScript的执行,预渲染你的应用有助于搜索引擎优化。 缺点 React是目标是UI组件,通常可以和其它框架组合使用,目前并不适合单独做一个完整的框架。React 即使配上 redux 的组合,也不能称之一个完整的框架,比如你想用Promise化的AJAX?对不起没有,自己找现成的库去。而且第三方组件远远不如Angular多。目前在大的稳定的项目上采用React的,我也就只知道有Yahoo的Email。React本身只是一个V而已,所以如果是大型项目想要一套完整的框架的话,也许还需要引入Redux和route相关的东西。 vue,react 共性: 虚拟dom实现快速渲染 轻量级响应式组件 服务端渲染易于集成路由工具,打包工具及状态管理工具 230、知道什么是vuex吗? 在SPA单页面组件的开发中 Vue的vuex和React的Redux 都统称为同一状态管理,个人的理解是全局状态管理更合适;简单的理解就是你在state中定义了一个数据之后,你可以在所在项目中的任何一个组件里进行获取、进行修改,并且你的修改可以得到全局的响应变更。 核心概念1: State state就是Vuex中的公共的状态, 我是将state看作是所有组件的data, 用于保存所有组件的公共数据. 核心概念2: Getters 我将getters属性理解为所有组件的computed属性, 也就是计算属性. vuex的官方文档也是说到可以将getter理解为store的计算属性, getters的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。 核心概念3: Mutations 我将mutaions理解为store中的methods, mutations对象中保存着更改数据的回调函数,该函数名官方规定叫type, 第一个参数是state, 第二参数是payload, 也就是自定义的参数. 核心概念4: Actions actions 类似于 mutations,不同在于:actions提交的是mutations而不是直接变更状态actions中可以包含异步操作, mutations中绝对不允许出现异步actions中的回调函数的第一个参数是context, 是一个与store实例具有相同属性和方法的对象
web前端—面试题汇总(216-220)216、说一下宏任务 web前端—面试题汇总(216-220) 216、说一下宏任务和微任务? 宏任务:当前调用栈中执行的任务称为宏任务。(主代码快,定时器等等)。 微任务: 当前(此次事件循环中)宏任务执行完,在下一个宏任务开始之前需要执行的任务为微任务。(可以理解为回调事件,promise.then,proness.nextTick等等)。 宏任务中的事件放在callback queue中,由事件触发线程维护;微任务的事件放在微任务队列中,由js引擎线程维护。 217、说一下继承的几种方式及优缺点? 说比较经典的几种继承方式并比较优缺点就可以了 借用构造函数继承,使用call或apply方法,将父对象的构造函数绑定在子对象上 原型继承,将子对象的prototype指向父对象的一个实例 组合继承 原型链继承的缺点 字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数。 借用构造函数(类式继承) 借用构造函数虽然解决了刚才两种问题,但没有原型,则复用无从谈起。 组合式继承 组合式继承是比较常用的一种继承方法,其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又保证每个实例都有它自己的属性。 218、说一下闭包? 闭包的实质是因为函数嵌套而形成的作用域链 闭包的定义即:函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包 219、export和export default的区别? 使用上的不同 export default xxx import xxx from './' export xxx import {xxx} from './' 220、说一下自己常用的es6的功能? 此题是一道开放题,可以自由回答。但要注意像let这种简单的用法就别说了,说一些经常用到并有一定高度的新功能 像module、class、promise等,尽量讲的详细一点。
web前端—面试题汇总(211-215)211、页面渲染ht web前端—面试题汇总(211-215) 211、页面渲染html的过程? 不需要死记硬背,理解整个过程即可 浏览器渲染页面的一般过程: 1.浏览器解析html源码,然后创建一个 DOM树。并行请求 css/image/js在DOM树中,每一个HTML标签都有一个对应的节点,并且每一个文本也都会有一个对应的文本节点。DOM树的根节点就是 documentElement,对应的是html标签。 2.浏览器解析CSS代码,计算出最终的样式数据。构建CSSOM树。对CSS代码中非法的语法它会直接忽略掉。解析CSS的时候会按照如下顺序来定义优先级:浏览器默认设置 < 用户设置 < 外链样式 < 内联样式 < html中的style。 http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2F3.DOM&urlrefer=e7de9a3bcbe654c9fcbf12c21ffa4ed5 Tree + CSSOM --> 渲染树(rendering tree)。渲染树和DOM树有点像,但是是有区别的。 DOM树完全和html标签一一对应,但是渲染树会忽略掉不需要渲染的元素,比如head、display:none的元素等。而且一大段文本中的每一个行在渲染树中都是独立的一个节点。渲染树中的每一个节点都存储有对应的css属性。 4.一旦渲染树创建好了,浏览器就可以根据渲染树直接把页面绘制到屏幕上。 以上四个步骤并不是一次性顺序完成的。如果DOM或者CSSOM被修改,以上过程会被重复执行。实际上,CSS和JavaScript往往会多次修改DOM或者CSSOM。/ 212、说一下CORS? CORS是一种新标准,支持同源通信,也支持跨域通信。fetch是实现CORS通信的 213、如何中断ajax请求? 一种是设置超时时间让ajax自动断开,另一种是手动停止ajax请求,其核心是调用XML对象的abort方法,ajax.abort()/ 214、说一下事件代理? 事件委托是指将事件绑定到目标元素的父元素上,利用冒泡机制触发该事件 ulEl.addEventListener('click', function(e){ var target = http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fevent.target&urlrefer=369b1404f1f7ce4cb4fe5b2afb1e31ba || event.srcElement; if(!!target && target.nodeName.toUpperCase() === "LI"){ console.log(target.innerHTML); } }, false); 215、target、currentTarget的区别? currentTarget当前所绑定事件的元素 target当前被点击的元素
web前端—面试题汇总(206-210)206、画一个三角形 web前端—面试题汇总(206-210) 206、画一个三角形? 这属于简单的css考查,平时在用组件库的同时,也别忘了原生的css .a{ width: 0; height: 0; border-width: 100px; border-style: solid; border-color: transparent #0099CC transparent transparent; transform: rotate(90deg); /*顺时针旋转90°*/ } <div class="a"></div> 207、清除浮动的几种方式,及原理? 清除浮动简单,但这题要引出的是BFC,BFC也是必考的基础知识点 ::after / <br> / clear: both 创建父级 BFC(overflow:hidden) 父级设置高度 BFC (块级格式化上下文),是一个独立的渲染区域,让处于 BFC 内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。 触发条件: 根元素 position: absolute/fixed display: inline-block / table float 元素 ovevflow !== visible 规则: 属于同一个 BFC 的两个相邻 Box 垂直排列 属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠 BFC 的区域不会与 float 的元素区域重叠 计算 BFC 的高度时,浮动子元素也参与计算 文字层不会被浮动层覆盖,环绕于周围 208、说一下<label>标签的用法 label标签主要是方便鼠标点击使用,扩大可点击的范围,增强用户操作体验 209、遍历A节点的父节点下的所有子节点 这题考查原生的js操作dom,属于非常简单的基础题,但长时间使用mvvm框架,可能会忘记 <script> var b=document.getElementById("a").parentNode.children; console.log(b) </script> 210、用js递归的方式写1到100求和? 递归我们经常用到,vue在实现双向绑定进行数据检验的时候用的也是递归,但要我们面试的时候手写一个递归,如果对递归的概念理解不透彻,可能还是会有一些问题。 function add(num1,num2){ var num = num1+num2; if(num2+1>100){ return num; }else{ return add(num,num2+1) } } var sum =add(1,2);
web前端—面试题汇总(201-205)201、calc, web前端—面试题汇总(201-205) 201、calc, support, media各自的含义及用法? @support主要是用于检测浏览器是否支持CSS的某个属性,其实就是条件判断,如果支持某个属性,你可以写一套样式,如果不支持某个属性,你也可以提供另外一套样式作为替补。 calc() 函数用于动态计算长度值。 calc()函数支持 "+", "-", "*", "/" 运算; @media 查询,你可以针对不同的媒体类型定义不同的样式。/ 202、css水平、垂直居中的写法,请至少写出4种? 这题考查的是css的基础知识是否全面,所以平时一定要注意多积累 水平居中 行内元素: text-align: center 块级元素: margin: 0 auto position:absolute +left:50%+ transform:translateX(-50%) display:flex + justify-content: center 垂直居中 设置line-height 等于height position:absolute +top:50%+ transform:translateY(-50%) display:flex + align-items: center display:table+display:table-cell + vertical-align: middle; 203、1rem、1em、1vh、1px各自代表的含义? rem rem是全部的长度都相对于根元素<html>元素。通常做法是给html元素设置一个字体大小,然后其他元素的长度单位就为rem。 em 子元素字体大小的em是相对于父元素字体大小 元素的width/height/padding/margin用em的话是相对于该元素的font-sizevw7h 全称是 Viewport Width 和 Viewport Height,视窗的宽度和高度,相当于 屏幕宽度和高度的 1%,不过,处理宽度的时候%单位更合适,处理高度的 话 vh 单位更好。 px px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。 一般电脑的分辨率有{1920*1024}等不同的分辨率 1920*1024 前者是屏幕宽度总共有1920个像素,后者则是高度为1024个像素/ 204、画一条0.5px的直线? 考查的是css3的transform height: 1px; transform: scale(0.5); 205、说一下盒模型? 盒模型是css中重要的基础知识,也是必考的基础知识 盒模型的组成,由里向外content,padding,border,margin. 在IE盒子模型中,width表示content+padding+border这三个部分的宽度 在标准的盒子模型中,width指content部分的宽度 box-sizing的使用 box-sizing: content-box 是W3C盒子模型 box-sizing: border-box 是IE盒子模型 box-sizing的默认属性是content-box
web前端—面试题汇总(191-195)191:请写出你对闭 web前端—面试题汇总(191-195) 191:请写出你对闭包的理解,并列出简单的理解 使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。 闭包有三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收 192:display none visibility hidden区别? 1.display:none是彻底消失,不在文档流中占位,浏览器也不会解析该元素;visibility:hidden是视觉上消失了,可以理解为透明度为0的效果,在文档流中占位,浏览器会解析该元素; 2.使用visibility:hidden比display:none性能上要好,display:none切换显示时visibility,页面产生回流(当页面中的一部分元素需要改变规模尺寸、布局、显示隐藏等,页面重新构建,此时就是回流。所有页面第一次加载时需要产生一次回流),而visibility切换是否显示时则不会引起回流。 193:JavaScript中如何检测一个变量是一个String类型?请写出函数实现 typeof(obj) === "string" typeof obj === "string" http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fobj.constructor&urlrefer=02a339a668d8be44474043343554f115 === String 194:如何理解闭包? 1、定义和用法:当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数内部的其它变量,如果返回的这个函数在外部被执行,就产生了闭包。 2、表现形式:使函数外部能够调用函数内部定义的变量。 3、实例如下: 根据作用域链的规则,底层作用域没有声明的变量,会向上一级找,找到就返回,没找到就一直找,直到window的变量,没有就返回undefined。这里明显count 是函数内部的flag2 的那个count 。 var count=10; //全局作用域 标记为flag1function add(){ var count=0; //函数全局作用域 标记为flag2 return function(){ count+=1; //函数的内部作用域 alert(count); } }var s = add() s();//输出1 s();//输出2 4、变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域。 变量的作用域分类:全局变量和局部变量。 特点: 1、函数内部可以读取函数外部的全局变量;在函数外部无法读取函数内的局部变量。 2、函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量! 3、使用闭包的注意点 1)滥用闭包,会造成内存泄漏:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。 2)会改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。 195:谈谈垃圾回收机制方式及内存管理 回收机制方式 1、定义和用法:垃圾回收机制(GC:Garbage Collection),执行环境负责管理代码执行过程中使用的内存。 2、原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。但是这个过程不是实时的,因为其开销比较大,所以垃圾回收器会按照固定的时间间隔周期性的执行。 3、实例如下: function fn1() { var obj = {name: 'hanzichi', age: 10}; } function fn2() { var obj = {name:'hanzichi', age: 10}; return obj; }var a = fn1();var b = fn2(); fn1中定义的obj为局部变量,而当调用结束后,出了fn1的环境,那么该块内存会被js引擎中的垃圾回收器自动释放;在fn2被调用的过程中,返回的对象被全局变量b所指向,所以该块内存并不会被释放。 4、垃圾回收策略:标记清除(较为常用)和引用计数。 标记清除:   定义和用法:当变量进入环境时,将变量标记"进入环境",当变量离开环境时,标记为:"离开环境"。某一个时刻,垃圾回收器会过滤掉环境中的变量,以及被环境变量引用的变量,剩下的就是被视为准备回收的变量。   到目前为止,IE、Firefox、Opera、Chrome、Safari的js实现使用的都是标记清除的垃圾回收策略或类似的策略,只不过垃圾收集的时间间隔互不相同。 引用计数:   定义和用法:引用计数是跟踪记录每个值被引用的次数。   基本原理:就是变量的引用次数,被引用一次则加1,当这个引用计数为0时,被视为准备回收的对象。
web前端—面试题汇总(181-185)181、什么叫优雅降 web前端—面试题汇总(181-185) 181、什么叫优雅降级和渐进增强? 渐进增强 progressive enhancement: 针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。 优雅降级 graceful degradation: 一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。 区别: a. 优雅降级是从复杂的现状开始,并试图减少用户体验的供给 b. 渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要 c. 降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带 182、sessionStorage 、localStorage 和 cookie 之间的区别 共同点:用于浏览器端存储的缓存数据 不同点: (1)、存储内容是否发送到服务器端:当设置了Cookie后,数据会发送到服务器端,造成一定的宽带浪费; web storage,会将数据保存到本地,不会造成宽带浪费; (2)、数据存储大小不同:Cookie数据不能超过4K,适用于会话标识;web storage数据存储可以达到5M; (3)、数据存储的有效期限不同:cookie只在设置了Cookid过期时间之前一直有效,即使关闭窗口或者浏览器; sessionStorage,仅在关闭浏览器之前有效;localStorage,数据存储永久有效; (4)、作用域不同:cookie和localStorage是在同源同窗口中都是共享的;sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面; 183、浏览器是如何渲染页面的? 渲染的流程如下: 1.解析HTML文件,创建DOM树。 自上而下,遇到任何样式(link、style)与脚本(script)都会阻塞(外部样式不阻塞后续外部脚本的加载)。 2.解析CSS。优先级:浏览器默认设置<用户设置<外部样式<内联样式<HTML中的style样式; 3.将CSS与DOM合并,构建渲染树(Render Tree) 4.布局和绘制,重绘(repaint)和重排(reflow) 184、js的基本数据类型 JavaScript中有五种基本数据类型,它们分别是:undefined,null,boolean,number,string。 还有一种复杂数据类型-object。 185、事件委托 事件委托就是利用的DOM事件的事件捕获阶段。把具体dom上发生的事件,委托给更大范围的dom去处理。好比送信员,如果每次都把信件送给每一户,非常繁琐。但是如果交给一个大范围的管理者,比如小区的传达室,那么事情会变得非常简单。事件委托就类似这种原理,我页面中有很多按钮,如果不使用事件委托,我只能在每个按钮上注册事件。非常麻烦。但如果我把事件注册在一个大范围的div(假设所有的按钮都在这个div中),那么我只要注册一次事件,就可以处理所有按钮(只要按钮包含在上述div中)事件的响应了
web前端—面试题汇总(166-170)166. 浏览器缓存 web前端—面试题汇总(166-170) 166. 浏览器缓存有哪些,通常缓存有哪几种 一、http缓存 二、websql cookie localstorage sessionstorage flash缓存 167.bootstrap响应式实现的原理 百分比布局+媒体查询 168.关于JS事件冒泡与JS事件代理(事件委托) 事件作为DOM操作重要的一环,需要大家好好理解和运用,今天特意看了一下事件冒泡和事件代理的相关资料,感触颇深,也深感自己的无知不知道多浪费了多少内存,废话不多说进入正题: 1.事件冒泡: 通俗易懂的来讲,就是当一个子元素的事件被触发的时候(如onclick事件),该事件会从事件源(被点击的子元素)开始逐级向上传播,触发父级元素的点击事件。 2.事件委托 事件委托,首先按字面的意思就能看你出来,是将事件交由别人来执行,再联想到上面讲的事件冒泡,是不是想到了?对,就是将子元素的事件通过冒泡的形式交由父元素来执行。下面经过详细的例子来说明事件委托: 有可能在开发的时候会遇到这种情况:如导航每一个栏目都要加一个事件,你可能会通过遍历来给每个栏目添加事件: 事件委托是怎 var ul = document.getElementById('parentUl'); ul.οnclick=function (event) { var e = event||window.event, source = http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fe.target&urlrefer=ce77446cd32f6ecb75e761eaa2e2ff8f || e.srcElement;//target表示在事件冒泡中触发事件的源元素,在IE中是srcElement if(source.nodeName.toLowerCase() == "li"){ //判断只有li触发的才会输出内容 alert(source.innerHTML); } stopPropagation(e); //阻止继续冒泡 }; function addElement() { var li = document.createElement('li'); li.innerHTML="我是新孩子"; ul.appendChild(li); } 169. CSS样式覆盖规则 规则一:由于继承而发生样式冲突时,最近祖先获胜。 规则二:继承的样式和直接指定的样式冲突时,直接指定的样式获胜 规则三:直接指定的样式发生冲突时,样式权值高者获胜。 样式的权值取决于样式的选择器,权值定义如下表。 CSS选择器 权值 标签选择器 1 类选择器 10 ID选择器 100 内联样式 1000 伪元素(:first-child等) 1 伪类(:link等) 10 可以看到,内联样式的权值>>ID选择器>>类选择器>>标签选择器,除此以外,后代选择器的权值为每项权值之和,比如”#nav .current a”的权值为100 + 10 + 1 = 111。 规则四:样式权值相同时,后者获胜。 规则五:!important的样式属性不被覆盖。 !important可以看做是万不得已的时候,打破上述四个规则的”金手指”。如果你一定要采用某个样式属性,而不让它被覆盖的,可以在属性值后加上!important,以规则四的例子为例,”.byline a {color:red !important;}”可以强行使链接显示红色。大多数情况下都可以通过其他方式来控制样式的覆盖,不能滥用!important。 170. 介绍一下box-sizing属性 兼容问题 首先,box-sizing属性在FireFox中存在兼容问题,所以需要使用-moz-box-sizing做一下兼容 属性值 · box-sizing:content-box · box-sizing:border-box · box-sizing:inherit content-box · 这是box-sizing的默认属性值 · 是CSS2.1中规定的宽度高度的显示行为 · 在CSS中定义的宽度和高度就对应到元素的内容框 · 在CSS中定义的宽度和高度之外绘制元素的内边距和边框 border-box · 在CSS中微元素设定的宽度和高度就决定了元素的边框盒 · 即为元素在设置内边距和边框是在已经设定好的宽度和高度之内进行绘制 · CSS中设定的宽度和高度减去边框和内间距才能得到元素内容所占的实际宽度和高度
web前端—面试题汇总(161-165)161.什么是mvv web前端—面试题汇总(161-165) 161.什么是mvvm mvc是什么区别 原理 一、MVC(Model-View-Controller) MVC是比较直观的架构模式,用户操作->View(负责接收用户的输入操作)->Controller(业务逻辑处理)->Model(数据持久化)->View(将结果反馈给View)。 MVC使用非常广泛,比如JavaEE中的SSH框架。 三、MVVM(Model-View-ViewModel) 如果说MVP是对MVC的进一步改进,那么MVVM则是思想的完全变革。它是将“数据模型数据双向绑定”的思想作为核心,因此在View和Model之间没有联系,通过ViewModel进行交互,而且Model和ViewModel之间的交互是双向的,因此视图的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应view。 162.px和em的区别 px表示像素 (计算机屏幕上的一个点:1px = 1/96in),是绝对单位,不会因为其他元素的尺寸变化而变化; em表示相对于父元素的字体大小。em是相对单位 ,没有一个固定的度量值,而是由其他元素尺寸来决定的相对值。 163.优雅降级和渐进增强 渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。 优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。 其实渐进增强和优雅降级并非什么新概念,只是旧的概念换了一个新的说法。在传统软件开发中,经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容 164.eval()的作用 把字符串参数解析成JS代码并运行,并返回执行的结果; eval("2+3");//执行加运算,并返回运算值。 eval("varage=10");//声明一个age变量 eval的作用域 functiona(){ 1. eval("var x=1"); //等效于 var x=1; 2. console.log(x); //输出1 3. } 4. a(); 5. console.log(x);//错误 x没有定 165. JS哪些操作会造成内存泄露 1)意外的全局变量引起的内存泄露 function leak(){ leak="xxx";//leak成为一个全局变量,不会被回收 } 2)闭包引起的内存泄露 3)没有清理的DOM元素引用 4)被遗忘的定时器或者回调 5)子元素存在引起的内存泄露
小白入门Python 爬虫干货之urllib库1. 小试牛刀 小白入门Python 爬虫干货之urllib库 1. 小试牛刀怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解释才呈现出来的,实质它是一段HTML代码,加 JS、CSS,如果把网页比作一个人,那么HTML便是他的骨架,JS便是他的肌肉,CSS便是它的衣服。所以最重要的部分是存在于HTML中的,下面我们就写个例子来扒一个网页下来 from http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Furllib.request&urlrefer=ae11e3d80e5efa564afbbce3e96a56ea import urlopenresponse = urlopen("http://www.baidu.com")print(response.read().decode())真正的程序就两行,执行如下命令查看运行结果,感受一下看,这个网页的源码已经被我们扒下来了,是不是很酸爽?2. 常见到的方法 requset.urlopen(url,data,timeout) 第一个参数url即为URL,第二个参数data是访问URL时要传送的数据,第三个timeout是设置超时时间。 第二三个参数是可以不传送的,data默认为空None,timeout默认为 socket._GLOBAL_DEFAULT_TIMEOUT 第一个参数URL是必须要传送的,在这个例子里面我们传送了百度的URL,执行urlopen方法之后,返回一个response对象,返回信息便保存在这里面。 response.read() read()方法就是读取文件里的全部内容,返回bytes类型 response.getcode() 返回 HTTP的响应码,成功返回200,4服务器页面出错,5服务器问题 response.geturl() 返回 返回实际数据的实际URL,防止重定向问题 http://response.info() 返回 服务器响应的HTTP报头 3. Request对象其实上面的urlopen参数可以传入一个request请求,它其实就是一个Request类的实例,构造时需要传入Url,Data等等的内容。比如上面的两行代码,我们可以这么改写 from http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Furllib.request&urlrefer=ae11e3d80e5efa564afbbce3e96a56ea import urlopenfrom http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Furllib.request&urlrefer=ae11e3d80e5efa564afbbce3e96a56ea import Requestrequest = Request("http://www.baidu.com")response = urlopen(requst)print response.read().decode()运行结果是完全一样的,只不过中间多了一个request对象,推荐大家这么写,因为在构建请求时还需要加入好多内容,通过构建一个request,服务器响应请求得到应答,这样显得逻辑上清晰明确4. Get 请求大部分被传输到浏览器的html,images,js,css, … 都是通过GET方法发出请求的。它是获取数据的主要方法例如:http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fwww.baidu.com&urlrefer=d04a537000146ae20785a6d0d3533551 搜索Get请求的参数都是在Url中体现的,如果有中文,需要转码,这时我们可使用 urllib.parse.urlencode() urllib.parse. quote() 5. Post 请求我们说了Request请求对象的里有data参数,它就是用在POST里的,我们要传送的数据就是这个参数data,data是一个字典,里面要匹配键值对发送请求/响应header头的含义:名称 | 含义 ---|--- Accept | 告诉服务器,客户端支持的数据类型 Accept-Charset | 告诉服务器,客户端采用的编码 Accept-Encoding | 告诉服务器,客户机支持的数据压缩格式 Accept-Language | 告诉服务器,客户机的语言环境 Host | 客户机通过这个头告诉服务器,想访问的主机名 If-Modified-Since | 客户机通过这个头告诉服务器,资源的缓存时间 Referer | 客户机通过这个头告诉服务器,它是从哪个资源来访问服务器的。(一般用于防盗链) User-Agent | 客户机通过这个头告诉服务器,客户机的软件环境 Cookie | 客户机通过这个头告诉服务器,可以向服务器带数据 Refresh | 服务器通过这个头,告诉浏览器隔多长时间刷新一次 Content-Type | 服务器通过这个头,回送数据的类型 Content-Language | 服务器通过这个头,告诉服务器的语言环境 Server | 服务器通过这个头,告诉浏览器服务器的类型 Content-Encoding | 服务器通过这个头,告诉浏览器数据采用的压缩格式 Content-Length | 服务器通过这个头,告诉浏览器回送数据的长度6. 响应的编码响应状态码响应状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。 常见状态码:号码 | 含义 -----|--- 100~199 | 表示服务器成功接收部分请求,要求客户端继续提交其余请求才能完成整个处理过程 200~299 | 表示服务器成功接收请求并已完成整个处理过程。常用200(OK 请求成功) 300~399 | 为完成请求,客户需进一步细化请求。例如:请求的资源已经移动一个新地址、常用302(所请求的页面已经临时转移至新的url)、307和304(使用缓存资源) 400~499 | 客户端的请求有错误,常用404(服务器无法找到被请求的页面)、403(服务器拒绝访问,权限不够) 500~599 | 服务器端出现错误,常用500(请求未完成。服务器遇到不可预知的情况)7. Ajax的请求获取数据有些网页内容使用AJAX加载,而AJAX一般返回的是JSON,直接对AJAX地址进行post或get,就返回JSON数据了8. 请求 SSL证书验证现在随处可见 https 开头的网站,urllib可以为 HTTPS 请求验证SSL证书,就像web浏览器一样,如果网站的SSL证书是经过CA认证的,则能够正常访问,如:https://www.baidu.com/如果SSL证书验证不通过,或者操作系统不信任服务器的安全证书,比如浏览器在访问12306网站如:https://www.12306.cn/mormhweb/的时候,会警告用户证书不受信任。(据说 12306 网站证书是自己做的,没有通过CA认证) # 忽略SSL安全认证context = ssl._create_unverified_context()# 添加到context参数里response = urllib.request.urlopen(request, context = context)
web前端—面试题汇总(076-080)每天坚持更新五道we web前端—面试题汇总(076-080) 每天坚持更新五道web前端开发面试题;点点关注,才会不迷路哦~~~~~ 076.一个页面有两个form,如何获取第一个form 用id方式获取;document.getElementById("id"); 077.如何设置一个层的可见/隐藏 可见 : document.getElementById("divid").http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fstyle.display&urlrefer=b496352c7c88f701336ee9428f058193 = "block"; 隐藏 : document.getElementById("divid").http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fstyle.display&urlrefer=b496352c7c88f701336ee9428f058193 = "none"; 078.描述JSP中动态INCLUDE与静态INCLUDE的区别? 动态导入 1、会将多个jsp页面分别再编写成java文件,编译成class文件 2、jsp文件中允许有相同的变量名,每个页面互不影响 3、当java代码比较多优先选用动态导入 4、效率相对较低,耦合性低 静态导入 1、会将多个jsp页面合成一个jsp页面,再编写成java文件,编译成class文件 2、jsp文件中不允许有相同的变量名 3、当java代码比较少或者没有java代码是优先选用静态导入 4、效率相对较高,耦合性高 079.列举JSP的内置对象及方法 request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie, header, 和session数据的有用的方法。 response表示HttpServletResponse对象,并提供了几个用于设置送回 浏览器的响应的方法(如cookies,头信息等) out对象是javax.jsp.JspWriter的一个实例,提供了几个方法使你能用于向浏览器回送输出结果 pageContext表示一个javax.servlejt.sp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,并且包装了通用的servlet相关功能的方法。 session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息 applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息 config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。 page表示从该页面产生的一个servlet实例 Exception异常 080.列举jsp的四大作用域 page、request、session、application
web前端—面试题汇总(071-075)每天坚持更新五道we web前端—面试题汇总(071-075) 每天坚持更新五道web前端开发面试题;点点关注,才会不迷路哦~~~~~ 71API中forward() 与redirect()的区别?答:为实现程序的模块化,就需要保证在不同的Servlet之间可以相互跳转,而Servlet中主要有两种实现跳转的方式:FORWARD方式与redirect方式。Forward() : 是服务器内部的重定向,服务器直接访问目标地址的URL,把那个URL的响应内容读取出来,而客户端并不知道,因此在客户端浏览器的地址栏里不会显示跳转后的地址,还是原来的地址。由于在整个定向的过程中用的是同一个Request,因此FORWARD会将Request的信息带到被定向的JSP或Servlet中使用。Redirect():则是客户端的重定向,是完全的跳转,即客户端浏览器会获取跳转后的地址,然后重新发送请求,因此浏览器中会显示跳转后的地址。同时,由于这种方式比FORWARD方式多了一次网络请求,因此其效率低于FORWARD方式,需要注意到的是,客户端的重定向可以通过设置特定的HTTP 头或写JavaScript脚本来实现。鉴于以上的区别,一般当FORWARD方式可以满足需求时,尽可能的使用FORWARD方式。但在有些情况下,例如,需要跳转到一个其他服务器上的资源时,则必须使用redirect 方式。 072.Session域和request域什么区别?作用域:存放数据,获取数据(传递数据)有效的作用域:生命周期,作用范围httpServeltRequest:生命周期:一次请求之间作用范围:所有被请求转发过的servlet都能获取到httpSession:生命周期:一次会话作用范围:所有的servlet都可以获取到servletContex:生命周期:从项目开始运行到服务器关闭作用范围:所有的servlet都可以获取到作用域如何选用?httpServeltRequest:和当前请求有关的信息httpSession:和当前用户有关的信息servletContex:访问量比较大,不易更改 073.页面中有一个命名为bankNo的下拉列表,写js脚本获取当前选项的索引值,如果用jquery如何获取var a = document.getElementsByName("bankNo")[0].value;var b = $("select[name=bankNo]").val(); 074.写出要求11位数字的正则表达式^[1-9]\d{10}$ 075.分别获取指定name、Id的javascript对象,如果用jquey如何获取 js: id--document.getElementById("id"); name--document.getElementsByName("name");jquery id--$("#id"); name--$("元素名称[name="name值"]");
web前端—面试题汇总(056-060)每天坚持更新五道we web前端—面试题汇总(056-060) 每天坚持更新五道web前端开发面试题;点点关注,才会不迷路哦~~~~~ 056.form中input设置为readonly和disabled的区别  057.CSS的定义和作用CSS的定义:CSS是Cascading Style Sheets(层叠样式表)的简称。CSS是一系列格式规则,它们控制网页内容的外观。CSS简单来说就是用来美化网页用的。CSS的具体作用包括:使网页丰富多彩,易于控制。页面的精确控制,实现精美、复杂页面 。 058.CSS2常用选择器类型及其含义  059.引入样式的三种方式及其优先级别三种引用方式:1. 外部样式表(存放.css文件中)不需要style标签 <linkrel=”stylesheet”href=”引用文件地址”/>2. 嵌入式样式表 <styletype=“text/css”>p{color:red;}</style>3.内联样式标签属性名为style <pstyle=“color:red;”></p>优先级级别:内联定义最高、内部CSS次之、外部CSS优先级最低。。 060.盒子模型盒子模型类似于生活中的盒子,具有4个属性,外边距,内边距,边框,内容。外边距:margin,用于设置元素和其他元素之间的距离。内边距:padding,用于设置元素内容和边框之间的距离。边框:border,用于设置元素边框粗细,颜色,线型。内容:width,height,用于设置元素内容显示的大小。 例如:  <style>body{margin:0;/*取消body默认的外边距*/}#img1{width:200px;/*设置图片的宽度*/border:2pxsolidblack;/*设置图片边框*/margin:5px;/*设置图片外边距(表示该图片与其他图片的距离为5px)*/padding:10px;/*设置图片与边框之间的距离*/}#img2{height:200px;/* 设置图片的高度*/border:2pxsolidblack;/*设置图片的边框*/margin:5px;/*设置图片外边距*/padding:20px;/*设置图片与边框之间的距离*/}</style><imgid="img1"src="img/2.jpg"/><imgid="img2"src="img/lss.jpg"/>
web前端—面试题汇总(051-055)051.HTML含义 web前端—面试题汇总(051-055) 051.HTML含义和版本变化HTML含义:Hyper Text Markup Language 超文本标记语言,是一种用来制作“网页”的简单标记语言;用HTML编写的超文本文档称为HTML文档,HTML文档的扩展名是html或者htm版本变化:HTML1.0——在1993年6月作为IETF工作草案发布(并非标准)HTML 2.0——1995年11月作为RFC 1866发布HTML 3.2——1997年1月14日,W3C推荐标准HTML 4.0——1997年12月18日,W3C推荐标准HTML 4.01(微小改进)——1999年12月24日,W3C推荐标准HTML 5—2014年10月28日,W3C推荐标准HTML文档结构;HTML 5.1 - 2016年HTML 5.2 – 2018年最新版本HTML 5.3 is coming… 052.什么是锚链接锚链接是带有文本的超链接。可以跳转到页面的某个位置,适用于页面内容较多,超过一屏的场合 。分为页面内的锚链接和页面间的锚链接 。例如:1F2F跳转到2F标记位置说明:1.在标记位置利用a标签的name属性设置标记。2.在导航位置通过a标签的href属性用#开头加name属性值即可跳转锚点位置。 053.HTML字符实体的作用及其常用字符实体有些字符,比如说“<”字符,在HTML中有特殊的含义,因此不能在文本中使用。想要在HTML中显示一个小于号“<”,需要用到字符实体:<或者<字符实体拥有三个部分:一个and符号(&),一个实体名或者一个实体号,最后是一个分号(;)常用字符实体:显示结果描述实体实体号空格 < 小于<<>大于> &#& and符号 & &' 单引号' (IE不支持) '" 引号" "£ 英镑£ £ ¥ 人民币元 ¥ ¥ § 章节 ¥ ¥ © 版权© © 054.HTML表单的作用和常用表单项类型表单的作用:利用表单可以收集客户端提交的有关信息。常用表单项类型:input标签type属性功能input标签type属性功能text单行本框reset重置按钮password密码框submit提交按钮radio单选按钮textarea文本域checkbox复选框select下拉框button普通按钮hidden隐藏域 055.表格、框架、div三种HTML布局方式的特点
2020,前端开发用什么工具?前端开发需要哪些软件?1.We 2020,前端开发用什么工具?前端开发需要哪些软件? 1.WebStorm【推荐】WebStorm 是jetbrains公司旗下一款JavaScript开发工具。被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。 [图片] 2.Visual Studio Code(简称:Vscode)【推荐】Visual Studio Code中文版是微软推出的带 GUI 的代码编辑器,软件功能非常强大,界面简洁明晰、操作方便快捷,设计得很人性化。软件主要改进了文档视图,完善了对 Markdown的支持,新增PHP语法高亮。 [图片] 3.Sublime TextSublime Text 是一个文本编辑器(收费软件,可以无限期试用,但是会有激活提示弹窗),同时也是一个先进的代码编辑器。Sublime Text是由程序员Jon Skinner于2008年1月份所开发出来,它最初被设计为一个具有丰富扩展功能的Vim。Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。 [图片] 4.HBuilderHBuilder是专为前端打造的开发工具,具有飞一样的编码、最全的语法库和浏览器兼容数据、可以方便的制作手机APP、最保护眼睛的绿柔设计等特点。支持HTML、CSS、JS、PHP的快速开发。 [图片] 5.Dreamweaverdreamweaver是美国MACROMEDIA公司开发的集网页制作和管理网站于一身的所见即所得网页编辑器。dreamweaver是第一套针对专业网页设计师特别发展的视觉化网页开发工具,利用它可以轻而易举地制作出跨越平台限制和跨越浏览器限制的充满动感的网页。 [图片] 6.notepad++Notepad++是Windows操作系统下的一套文本编辑器(软件版权许可证:GPL),有完整的中文化接口及支持多国语言编写的功能(UTF8技术)。Notepad++功能比Windows中的Notepad(记事本)强大,除了可以用来制作一般的纯文字说明文件,也十分适合编写计算机程序代码。Notepad++ 不仅有语法高亮度显示,也有语法折叠功能,并且支持宏以及扩充基本功能的外挂模组。 [图片] 7.editplusEditPlus是一款由韩国 Sangil Kim (ES-Computing)出品的小巧但是功能强大的可处理文本、HTML和程序语言的Windows编辑器,你甚至可以通过设置用户工具将其作为C,Java,Php等等语言的一个简单的IDE。 [图片] 8.记事本写代码 [图片]
web前端—面试题汇总(036-040)036.TCP为何采 web前端—面试题汇总(036-040) 036.TCP为何采用三次握手来建立连接,若釆用二次握手可以吗,请说明理由? 三次握手是为了防止已失效的连接请求再次传送到服务器端。 二次握手不可行,因为:如果由于网络不稳定,虽然客户端以前发送的连接请求以到达服务方,但服务方的同意连接的应答未能到达客户端。则客户方要重新发送连接请求,若采用二次握手,服务方收到重传的请求连接后,会以为是新的请求,就会发送同意连接报文,并新开进程提供服务,这样会造成服务方资源的无谓浪费 037.以下HTTP相应状态码的含义描述正确的是() A.200ok表示请求成功 B.400不良请求表示服务器未发现与请求URL匹配内容 C.404未发现表示由于语法错误儿导致服务器无法理解请求信息 D.500内部服务器错误,无法处理请求 答案:D 分析: A 200ok 表示的意思是一切正常。一般用于相应GET和POST请求。这个状态码对servlet是缺省的;如果没有调用setStatus方法的话,就会得到200。 B 400 表示指出客户端请求中的语法错误 C 404 客户端所给的地址无法找到任何资源 038.JSP页面包括哪些元素?() A.JSP命令 B.JSP Action C.JSP脚本 D.JSP控件 答案:C 分析:JSP页面元素构成如下,因此ABD错误 A 200ok 表示的意思是一切正常。一般用于相应GET和POST请求。这个状态码对servlet是缺省的;如果没有调用setStatus方法的话,就会得到200。 B 400 表示指出客户端请求中的语法错误 C 404 客户端所给的地址无法找到任何资源 [图片] 039.Ajax有四种技术组成:DOM,CSS,JavaScript,XmlHttpRequest,其中控制文档结构的是() A. DOM B.CSS C.JavaScript D.XmlHttpRequest 答案:A 040.下面关于session的用法哪些是错误的?() A.HttpSession session=new HttpSession(); B.String haha=session getParameler(:haha”); C.session.removeAttribute(“haha”); D.session.setAttribute(:haha:);XmlHttpRequest 答案:A
新手入门-冒泡排序和选择排序第一节排序1.1排序概述排序( 新手入门-冒泡排序和选择排序 第一节排序 1.1排序概述 排序(sorting)的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列。  内部排序和外部排序 一类是整个排序过程在内存储器中进行,称为内部排序; 另一类是由于待排序元素数量太大,以至于内存储器无法容纳全部数据,排序需要借助外部存储设备才能完成,这类排序称为外部排序。 本章介绍的排序方法都属于内部排序 比较排序和非比较排序 大部分排序都是需要通过比较首先来判断大小,作为排序的依据的。 但是也有例外的,比如计数排序、基数排序,不需要进行比较。效率可以做到更高,但是会有一些限制条件,也可能需要更多的空间。 冒泡排序、选择排序、直接插入排序是最基本的三种排序,效率最低,但是算法简单。排序的学习一般从这三种排序算法开始。 1.2冒泡排序 冒泡排序的算法 1) 整个数列分成两部分:前面是无序数列,后面是有序数列 2) 初始状态下,整个数列都是无序的,有序数列是空 3) 如果一个数列有n个元素,则至多需要n-1趟循环才能保证数列有序 4) 每一趟循环可以让无序数列中最大数排到最后,(也就是说有序数列的元素个数增加1) 5) 每一趟循环都从数列的第一个元素开始进行比较,依次比较相邻的两个元素,比较到无序数列的末尾即可(而不是数列的末尾) 6) 如果前一个大于后一个,交换 【示例1】冒泡排序算法 public class TestBubbleSort1{ public static void main(String [] args){ //定义一个无序数组 int [] arr = {75,87,56,45,89,100,76,34,89,97}; //排序前输出 System.out.println("排序前"); for(int score :arr){ System.out.print(score+"\t"); } //排序 //大循环:n个元素排序,则至多需要n-1趟循环 for(int i=0;i<arr.length-1;i++){ //小循环:每一趟循环都从数列的前两个元素开始进行比较, //比较到数组的最后 for(int j=0;j<arr.length-1;j++){ //如果前一个大于后一个 if(arr[j] > arr[j+1]){ //交换 int temp; temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } //排序后输出 System.out.println("\n排序后"); for(int score :arr){ System.out.print(score+"\t"); } } } 缺点1:每一趟比较都要比较到数组的最后,没有必要,只要比较到无序数列的最后即可 for(int j=0;j<scoreArr.length-1;j++){ } i j<? 0 <6 1 <5 2 <4 3 <3 i j<6-i scoreArr.length-1-i 解决:j<scoreArr.length-1 修改为 j<scoreArr.length-1-i 缺点2:不管是否有序,都要进行n-1趟循环; 如何判断有序:比较了一趟,没有发生交换 解决:定义一个符号量flag,默认有序true;发生交换,置为false, 一趟循环结束后,根据flag的值判断是否有序;有序,退出即可; 【示例2】完善冒泡排序算法 public class TestBubbleSort2{ public static void main(String [] args){ //定义一个无序数组 int [] arr = {75,87,56,45,89,100,76,34,89,97}; //排序前输出 System.out.println("排序前"); for(int score :arr){ System.out.print(score+"\t"); } //排序 bubbleSort(arr); //排序后输出 System.out.println("排序后"); for(int score :arr){ System.out.print(score+"\t"); } } public static void bubbleSort(int arr[]){ //大循环:n个元素排序,则至多需要n-1趟循环 int temp; int i; for(i=0;i<arr.length-1;i++){ //1. 假设有序 boolean flag = true; //2.小循环:每一趟循环都从数列的前两个元素开始进行比较, // 比较到数组的最后 for(int j=0;j<arr.length-1-i;j++){ //如果前一个大于后一个 if(arr[j] > arr[j+1]){ //交换 temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; //发生了交换,数组无序 flag = false; } } //3.判断是否有序,有序,退出 if(flag){ break; } } //System.out.println("\n一共进行了"+(i+1)+"趟循环"); } } 1.3 选择排序 选择排序的算法 1) 整个数列分成两部分:前面是有序数列,后面是无序数列 2) 初始状态下,整个数列都是无序的,有序数列是空 3) 一共n个数,需要n-1趟循环(一趟都不能少) 4) 每比较完一趟,有序数列数量+1,无序数列数量-1 5) 每趟先假设无序数列的第1个元素(整个数列的第i个元素)是最小的,让当前的最小数,从第i+1个元素开始比较,一直比较到最后一个元素。如果发现更小的数,就假设当前数是最小数。 6) 一趟比较完后,将发现最小数和无序数列的第一个数交换(如果最小数不是无序数列的第一个数) 【示例3】选择排序 public class TestSelectSort { public static void main(String[] args) { //给定无序的数组 int [] scoreArr = {75,87,56,45,89,100,76,34,89,97}; //输出无序的数组 System.out.println(Arrays.toString(scoreArr)); //选择排序 selectSort(scoreArr); //输出有序的数组 System.out.println(Arrays.toString(scoreArr)); } public static void selectSort(int[] scoreArr) { //大循环:n个元素排序,则需要n-1趟循环 for(int i=0;i<scoreArr.length-1;i++){ //第i趟先假设第i个最小 int minIndex = i; //从第i+1个元素开始,依次使用最小元素和每元素比较,一直比较到最后 for (int j = i+1; j <scoreArr.length ; j++) { if(scoreArr[minIndex] > scoreArr[j]){ minIndex = j; } } //一趟比较完后,或者最小值的索引,如果不是第i个,就交换 if(minIndex !=i){ int temp; temp = scoreArr[i]; scoreArr[i] = scoreArr[minIndex]; scoreArr[minIndex] = temp; } } } } 注意 q 冒泡排序最多需要n-1趟循环,最少1趟循环;选择排序必须进行n-1趟循环,一趟也不能少 q 冒泡排序中最多的操作就是比较和交换,一趟循环中可能发生多次交换;而选择排序中最多的操作是比较,一趟比较结束后如果发现更小的值才交换一次。 q 如果数组元素不是基本数据类型,而是对象,应该如何判断大小呢?可以让相应类实现Comparable接口并调用comparTo()方法进行比较。 q 快速排序是冒泡排序的完善版,都是基于交换的排序,是各种基于比较的排序算法中效率最高的,用到了分治和递归的思想。需要认真准备。 本节作业 1. 使用冒泡排序实现对分数排序 2. 使用选择排序实现对分数排序 3. 可选:使用选择排序实现对课程名称(比如Java、MySQL等)按照字母排序 4. 可选:查询资料掌握直接插入排序算法并实现对分数排序
微信小程序开发用户授权登录(下)来自专栏胖梅老师说前端5 人 微信小程序开发用户授权登录(下) 来自专栏胖梅老师说前端 5 人赞同了文章 为你朗读 2分钟 如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过 UnionID 来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的 UnionID 是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。所以我们有时候需要获取这个UnionID 登录流程 流程解析 1. 客户端获得code,并将code传给第三方服务端(后台) 微信小程序端调用wx.login,获取登录凭证(code),并调用接口,将code发送到第三方客户端 2. 第三方服务端用code换session_key和openid 小程序端将code传给第三方服务器端,第三方服务器端调用接口,用code换取session_key和 openid (后台服务器带着前端发送的code去访问微信后台的接口) 3. 第三方服务端生成新的session_key和 openid 第三方服务器端拿到请求回来的session_key和openid,发送到客户端 4. 正常请求 小程序每次请求都将openid 放在请求头里,第三方服务端解析判断合法性,并进行正常的逻辑处理 小程序 wx.checkSession 校验登陆态 success :接口调用成功,session_key未过期; fail :接口调用失败,session_key已过期; 代码演示 代码分两种演示:第一种自己启动了本地的后台 访问微信公共平台 另外一个会给大家提供一个模拟演示的接口 获取session_key openid 登录页.wxml 可以只是一个简单的按钮 点击 button去登录 登录页.js 这样就登录完成了。
微信小程序开发用户授权登录(上)思路:1.点击 按钮授权 绑 微信小程序开发用户授权登录(上) 思路: 1.点击 按钮授权 绑定点击事件 <button open-type="getUserInfo" bindgetuserinfo='getUserInfo'>获取头像昵称 </button> 2.事件获取e 获取授权信息 console.log(e.detail)//userInfo登录人微信信息 3.进入页面 获取之前有没有授权过 ---在app.js获取信息 设置成全局 wx.getSetting({}) success--->res.authSetting['scope.userInfo'] 判断授权 wx.getUserInfo({}) success-->userInfo 用户信息 4.about.js 判断全局授权信息 实现效果:  第一步:授权界面  about.wxml代码 <!-- 登录授权 --> <view wx:if='{{isShow}}'> <view wx:if='{{canIuse}}'> <button open-type="getUserInfo" bindgetuserinfo='getUserInfo'>获取头像昵称 </button> </view> <view wx:else>请升级微信版本</view> </view> <!-- 内容显示--头像 --> <view class='userinfo' wx:else> <view class="avatarUrl"> <image src='{{userInfo.avatarUrl}}'></image></view> <text class='nickName'>{{userInfo.nickName}}</text> </view> 第二步:获取头像事件 bindgetuserinfo  about.js代码 后面演示---最下面 第三步:再次进入页面后 获取是否授权过 app.js app.js代码 App({ onLaunch:function(){ var that=this; //进入页面获取是否授权---------------------------- wx.getSetting({ success(res) {//authSetting用户授权结果 console.log(res.authSetting); //scope.userInfo if (res.authSetting['scope.userInfo']) {//授权过 console.log('授权过信息'); // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 wx.getUserInfo({ success: function (res) { console.log(res.userInfo); //存储到本地 that.globalData.userInfo = res.userInfo; // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 // 所以此处加入 callback 以防止这种情况 if (that.userInfoReadyCallback) { that.userInfoReadyCallback(res) } } }) } else { console.log('没有授权') } } }) wx.showModal({ title: '是否授权当前的用户信息', content: '', }) }, globalData: { cityInfo: '', userInfo:null, } }) 第四步:进入我的登录界面 获取用户头像信息  代码: var app=getApp(); Page({ data: { isShow:true,//显示 //判断小程序的API,回调,参数,组件等是否在当前版本可用 canIuse: wx.canIUse('button.open-type.getUserInfo'), userInfo:{},//微信信息 }, onLoad: function (options) { //进入页面---判断全局是否有数据 var that=this; console.log(app.globalData.userInfo) //进入页面后---获取本地存储是否有数据授权---------- if(app.globalData.userInfo){ this.setData({ isShow:false, userInfo:app.globalData.userInfo }) } else if (this.data.canIuse) { // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 // 所以此处加入 callback 以防止这种情况 app.userInfoReadyCallback = res => { that.setData({ userInfo: res.userInfo, isShow: false, }) } } }, //-----点击授权-------------------------- getUserInfo:function(e){ console.log(e.detail)//userInfo登录人微信信息 //存储全局变量----------------- app.globalData.userInfo = e.detail.userInfo;//存全局的账号信息 this.setData({ userInfo:e.detail.userInfo, isShow:false }) },})
java入门必看--HashMap底层原理和手写HashMa java入门必看--HashMap底层原理和手写HashMap 3.1 HashMap的原理 • 底层结构是哈希表,采用了顺序表+链表结合结构;同一个链表的上所有元素的存储地址都是相同的,是发生冲突的元素  • 链表上每个节点的就是一个Entry,字段包括四部分  问:同一个链表上节点的哈希码相同吗??哈希码可能不相同,存储地址相同。 • 哈希表的优点 • 添加快、查询快(通过计算得到存储位置,不是通过比较) • 无序 • (key)唯一 • 关键参数 • 默认主数组长度16; • 默认装填因子0.75。 • 每次主数组扩容为原来的2倍 • JDK8,当链表长度大于8,链表变成红黑树  • 第一步计算哈希码,不仅调用了hashCode(),有进行了多次散列。目的在于key不同,哈希码尽量不同,减少冲突 final int hash(Object k) { int h = 0; h ^= k.hashCode(); h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } • 细节:发生冲突,经过比较不存在相同key的元素,要添加一个新的节点。不是加到链表最后,而是添加到链表最前   3.2定义Map接口 【示例11】 定义Map接口 public interface Map { //定义方法 public void put(Object key,Object value); public Object get(Object key); public int size(); public boolean isEmpty(); //定义内部接口 interface Entry{ public Object getKey(); public Object getValue(); } } 3.3手写HashMap 【示例12】 手写HashMap public class HashMap implements Map { public Entry[] table;//指向哈希表的数组引用 int size;//键值对的数量 public HashMap() { table = new Entry[11];//哈希表主数组默认长度16 } public void put(Object key, Object value) { //计算哈希码 int hash = key.hashCode(); //根据哈希码计算存储位置 int index = hash % table.length; //存入指定位置 if (table[index] == null) {//如果该位置没有元素,增加一个节点 table[index] = new Entry(hash, key, value); size++; } else {//如果有元素,进行逐个比较 Entry entry = table[index]; //Entry previousEntry = null; while (entry != null) { //如果找到了相同的key if (entry.getKey().equals(key)) { //新的value替代旧的value entry.value = value; return; } //previousEntry = entry; entry = entry.next; } //循环结束,表明也没有相同的key,在链表最后添加一个节点 //previousEntry.next = new Entry(hash, key, value); //循环结束,表明也没有相同的key,在链表最前边添加一个节点 Entry firstEntry = table[index]; table[index] = new Entry(hash, key, value,firstEntry); size++; } } public Object get(Object key) { //计算哈希码 int hash = key.hashCode(); //根据哈希码计算存储位置 int index = hash % table.length; //查找对应的Entry Entry entry = null; if (table[index] != null) { Entry currentEntry = table[index]; while (currentEntry != null) { if (currentEntry.getKey().equals(key)) { entry = currentEntry; break; } currentEntry = currentEntry.next; } } return entry == null ? null : entry.getValue(); } public String toString() { StringBuilder builder = new StringBuilder("{"); for(int i=0;i<table.length;i++){ if(table[i] != null){ Entry entry = table[i]; while(entry != null){ builder.append(entry.getKey()+"="+entry.getValue()+","); entry = entry.next; } } } if(builder.length()!=1){ builder.deleteCharAt(builder.length()-1); } builder.append("}"); return builder.toString(); } public int size() { return size; public boolean isEmpty() { return size == 0; } class Entry implements Map.Entry { private int hash;//哈希码 private Object key;//键 private Object value;//值 private Entry next;//指向下一个节点的指针 public Entry() { } public Entry(int hash, Object key, Object value) { this.hash = hash; this.key = key; this.value = value; } public Entry(int hash, Object key, Object value, Entry next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } public Object getKey() { return key; } public Object getValue() { return value; } public String toString() { if (next != null) { return "{" + key + ":" + value + "-" + hash + " " + next + "}"; } else { return "{" + key + ":" + value + "-" + hash + "}"; } } } } 1.4测试HashMap 【示例13】 测试HashMap public class TestHashMap { public static void main(String[] args) { java.util.HashMap map2; HashMap map = new HashMap(); map.put(23,"China"); map.put(36,"Japan"); map.put(48,"America"); map.put(86,"the United States"); map.put(67,"France"); map.put(23,"Italian"); map.put(47,"England"); System.out.println(map.size()); System.out.println(Arrays.toString(map.table)); System.out.println(map); } }
新手入门必看-线程同步锁-Lock锁本文主要内容:线程同步的 新手入门必看-线程同步锁-Lock锁 本文主要内容: 线程同步的概念和使用场景 使用同步代码块 使用同步方法 使用lock锁 三种方式实现窗口售票 本文作业 1 问题的提出 •应用场景: • 多个用户同时操作一个银行账户。每次取款400元,取款前先检查余额是否足够。如果不够,放弃取款 •分析 • 使用多线程解决 • 开发一个取款线程类,每个用户对应一个线程对象 • 因为多个线程共享同一个银行账户,使用Runnable方式解决 •思路 • 创建银行账户类Account • 创建取款线程AccountRunnable • 创建测试类TestAccount,让两个用户同时取款 【示例9】引入线程同步 /** * 银行账户 */ public class Account { private int balance = 600; //取款 public void withDraw(int money){ this.balance = this.balance - money; } //查看余额 public int getBalance(){ return balance; } } public class AccountRunnable implements Runnable { private Account account = new Account(); @Override public void run() { //判断余额是否足够,够,取之;不够,不取之; if(account.getBalance()>=400){ try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } //取之 account.withDraw(400); //输出信息 System.out.println(Thread.currentThread().getName()+ "取款成功,现在的余额是"+account.getBalance()); }else{ System.out.println("余额不足,"+Thread.currentThread().getName() +"取款失败,现在的余额是" +account.getBalance()); } } } public class Test { public static void main(String[] args) { //创建两个线程 Runnable runnable = new AccountRunnable(); Thread zhangsanThread = new Thread(runnable); Thread zhangsanWifeThread =new Thread(runnable,"张三妻子"); zhangsanThread.setName("张三"); //启动两个线程 zhangsanThread.start(); zhangsanWifeThread.start(); } } 分析:使用Thread.sleep()的目的在于模拟线程切换,在一个线程判断完余额后,不是立刻取款,而是让出CPU,这样另外一个线程获取CPU,并且进行余额的判断。线程安全问题就这么产生了。如果保证安全,必须判断余额和取款的语句必须被一个线程执行完才能让另外一个线程执行。 •当多个线程访问同一个数据时,容易出现线程安全问题。需要让线程同步,保证数据安全 •线程同步 • 当两个或两个以上线程访问同一资源时,需要某种方式来确保资源在某一时刻只被一个线程使用 •线程同步的实现方案 • 同步代码块 • synchronized (obj){ } • 同步方法 • private synchronized void makeWithdrawal(int amt) {} • Lock锁 2同步代码块 【示例10】使用同步代码块实现线程同步 public class AccountRunnable implements Runnable { private Account account = new Account(); @Override public void run() { //此处省略300句 synchronized (account){ //锁 //判断余额是否足够,够,取之;不够,不取之; if(account.getBalance()>=400){ try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } //取之 account.withDraw(400); //输出信息 System.out.println(Thread.currentThread().getName() +"取款成功,现在的余额是"+account.getBalance()); }else{ System.out.println("余额不足,"+Thread.currentThread().getName() +"取款失败,现在的余额是"+account.getBalance()); } } //此处省略200句 } } 总结1:认识同步监视器(锁子) · synchronized(同步监视器){ } 1) 必须是引用数据类型,不能是基本数据类型 2) 在同步代码块中可以改变同步监视器对象的值,不能改变其引用 3) 尽量不要String和包装类Integer做同步监视器.如果使用了,只要保证代码块中不对其进行任何操作也没有关系 4) 一般使用共享资源做同步监视器即可 5) 也可以创建一个专门的同步监视器,没有任何业务含义 6) 建议使用final修饰同步监视器 总结2:同步代码块的执行过程 1) 第一个线程来到同步代码块,发现同步监视器open状态,需要close,然后执行其中的代码 2) 第一个线程执行过程中,发生了线程切换(阻塞 就绪),第一个线程失去了cpu,但是没有开锁open 3) 第二个线程获取了cpu,来到了同步代码块,发现同步监视器close状态,无法执行其中的代码,第二个线程也进入阻塞状态 4) 第一个线程再次获取CPU,接着执行后续的代码;同步代码块执行完毕,释放锁open 5) 第二个线程也再次获取cpu,来到了同步代码块,发现同步监视器open状态,重复第一个线程的处理过程(加锁) 强调:同步代码块中能发生线程切换吗?能!!!但是后续的被执行的线程也无法执行同步代码块(锁仍旧close) 总结3:线程同步 优点和缺点 · 优点:安全 · 缺点:效率低下 可能出现死锁 总结4:其他 1) 多个代码块使用了同一个同步监视器(锁),锁住一个代码块的同时,也锁住所有使用该锁的所有代码块,其他线程无法访问其中的任何一个代码块 2) 多个代码块使用了同一个同步监视器(锁),锁住一个代码块的同时,也锁住所有使用该锁的所有代码块, 但是没有锁住使用其他同步监视器的代码块,其他线程有机会访问其他同步监视器的代码块 3同步方法 【示例11】使用同步方法实现线程同步 public class AccountRunnable implements Runnable { private Account account = new Account(); @Override public void run() { //此处省略300句 //判断余额是否足够,够,取之;不够,不取之; withDraw(); //此处省略200句 } public synchronized void withDraw(){ //同步监视器都是this if(account.getBalance()>=400){ try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } //取之 account.withDraw(400); //输出信息 System.out.println(Thread.currentThread().getName()+ "取款成功,现在的余额是"+account.getBalance()); }else{ System.out.println("余额不足,"+Thread.currentThread().getName() +"取款失败,现在的余额是" +account.getBalance()); } } public synchronized void method2(){ //this } public synchronized void method3(){ //this } } 总结:关于同步方法 1) 不要讲run()定义为同步方法 2) 同步方法的同步监视器是this 3) 同步代码块的效率要高于同步方法 u 同步方法的锁是this,一旦锁住一个方法,就锁住了所有的同步方法;同步代码块只是锁住使用该同步监视器的代码块,而没有锁住使用其他监视器的代码块 u 同步方法是将线程锁在了方法的外部,而同步代码块锁将线程锁在了代码块的外部,但是却是方法的内部 4 Lock锁 JDK1.5中推出了新一代的线程同步方式:Lock锁 【示例12】使用Lock锁实现线程同步 public class AccountRunnable implements Runnable { private Account account = new Account(); //买一把锁 Lock lock = new ReentrantLock(); //Re-entrant-Lock 可重入锁 @Override public void run() { //此处省略300句 try{ //上锁 lock.lock(); //判断余额是否足够,够,取之;不够,不取之; if(account.getBalance()>=400){ try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } method1(); //取之 account.withDraw(400); //输出信息 System.out.println(Thread.currentThread().getName()+ "取款成功,现在的余额是"+account.getBalance()); }else{ System.out.println("余额不足,"+Thread.currentThread().getName() +"取款失败,现在的余额是" +account.getBalance()); } }finally { //解锁 lock.unlock(); } //此处省略100句 } } • Lock锁 • JDK1.5后新增功能,与采用synchronized相比,lock可提供多种锁方案,更灵活 • java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。这就为 Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特性或者锁定语义。 • ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义, 但是添加了类似锁投票、定时锁等候和可中断锁等候的一些特性。此外,它还提供了在激烈争用情况下更佳的性能。 • 注意:如果同步代码有异常,要将unlock()写入fina
手写单链表和LinkedList2.1单链表技能点·认识 手写单链表和LinkedList 2.1单链表技能点 ·认识单链表   o特点 数据元素的存储对应的是不连续的存储空间,每个存储结点对应一个需要存储的数据元素。 每个结点是由数据域和指针域组成。 元素之间的逻辑关系通过存储节点之间的链接关系反映出来。逻辑上相邻的节点物理上不必相邻。 o缺点: 1. 比顺序存储结构的存储密度小 (每个节点都由数据域和指针域组成, 所以相同空间内假设全存满的话顺序比链式存储更多)。 2. 按照索引查找结点时链式存储要比顺序存储慢(每个节点地址不连续、无规律,导致按照索引查询效率低下。 o优点: 1. 插入、删除灵活 (不必移动节点,只要改变节点中的指针,但是需要先定位到元素上)。 2. 有元素才会分配结点空间,不会有闲置的结点。 ·添加节点 ·删除节点 ·带头节点的单链表 在使用单链表实现线性表的时候,为了使程序更加简洁,我们通常在单链表的最前面添加一个哑元结点,也称为头结点。 在头结点中不存储任何实质的数据对象,其 next 域指向线性表中 0 号元素所在的结点, 可以对空表、非空表的情况以及对首元结点进行统一处理,编程更方便,常用头结点。 一个不带头结点和带头结点的单链表实现线性表的结构图如图所示。 2.2手写单链表 •定义单链表节点 【示例5】定义单链表节点 public class Node { Object data;//存储是数据 Node next;//指向下个节点的指针 public Node() { super(); } public Node(Object data) { super(); this.data = data; } public Node(Object data, Node next) { super(); this.data = data; this.next = next; } //省略setter和getter方法 public String toString() { return "Node [data=" + data + ", next=" + next + "]"; } } •手写单链表 【示例6】手写单链表 public class SingleLinkedList implements List { //头节点 哑巴节点 不存储数据 为了方便编程 private Node head = new Node(); private int size = 0;//节点的个数 public int size() { return size; } public Object get(int i) { //i从0开始 //判断i的值是否合理 if(i<0 || i>=size){ throw new IndexOutOfBoundsException("索引越界"+i); } //顺藤摸瓜,从第一个节点开始查找 Node p = head.next;//p初始指向第一个节点(不是头节点) for(int j=0;j<i;j++){ //p指向下个节点 p=p.next; } //return p.data;//返回的不是第i个节点,而是第i个节点的data return p;//返回的是第i个节点,而不是第i个节点的data } public boolean isEmpty() { return size==0; } public void add(int i, Object e) { //i值合理性判断 if(i<0 || i>size){ throw new IndexOutOfBoundsException("索引越界"+i); } //先找到前一个(如果当前索引是0,前一个就是head) Node p = head; if(i!=0){ p = (Node)this.get(i-1); } //创建一个新节点,给data赋值 Node newNode = new Node(e); //指定新节点的下一个节点 newNode.next = p.next; //指定前一个节点的下个节点是当前新节点 p.next = newNode; //数量+1 size++; } public void add(Object e) { this.add(size, e); } public Object remove(int i) { //i值合理性判断 if(i<0 || i>=size){ throw new IndexOutOfBoundsException("索引越界"+i); } //先找到前一个(如果当前索引是0,前一个就是head) Node p = head; if(i!=0){ p = (Node)this.get(i-1); } //指向要删除的节点 Node currNode = p.next; //完成删除操作 p.next = currNode.next; currNode.next = null; currNode = null;//提示将要删除的节点变成垃圾 //数量-1 size--; return null; } public String toString() { StringBuilder builder = new StringBuilder("["); Node p = head.next;//p初始指向第一个节点(不是头节点) for(int j=0;j<size;j++){ builder.append(p.data+" "); //p指向下个节点 p=p.next; } builder.append("]"); return builder.toString(); } } 单链表添加删除查询原理 •测试单链表 【示例7】测试单链表 public class TestList { public static void main(String[] args) { java.util.ArrayList list2; //创建线性顺序表 List list = new SingleLinkedList(); //向末尾添加元素 list.add("11111"); list.add("aaaaa"); list.add("bbbbb"); list.add("33333"); list.add("22222"); list.add(3, "AAAAA"); list.remove(2); //进行各种操作验证添加 System.out.println(list.size()); System.out.println(list.isEmpty()); System.out.println(list.contains("44444")); System.out.println(list.indexOf("22222")); System.out.println(list.toString()); } } 2.3 手写LinkedList ·LinkedList底层原理 ² LinkedList底层是一个双向链表;添加、删除元素效率高;按照索引查询效率低。可以两个方向查询 ² 每个节点都包含了对前一个和后一个元素的引用 ² LinkedList同时实现了List、Deque、Queue接口,所以可以当做线性表、队列、双端队列、栈使用 ² LinkedList 是非同步的(线程不安全) ² 不存在LinkedList容量不足的问题 ·定义LinkedList节点 【示例8】定义LinkedList节点 public class LinkedList implements List { /** * 静态内部类 代表LinkedList的每个节点 */ private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } @Override public String toString() { return "Node{" + "item=" + item +", next=" + next +'}'; } } } ·手写LinkedList 【示例9】手写LinkedList public class LinkedList implements List { transient int size = 0; transient Node first; transient Node last; public int size() { return size; } public Object get(int i) { return node(i).item; } public boolean isEmpty() { return size ==0; } public void add(int index, Object element) { if (index == size) linkLast(element); else linkBefore(element, node(index)); } Node node(int index) { if (index < (size >> 1)) { Node x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } } void linkBefore(Object e, Node succ) { final Node pred = succ.prev; final Node newNode = new Node<>(pred, e, succ); succ.prev = newNode; if (pred == null) first = newNode; else pred.next = newNode; size++; } public void add(Object e) { linkLast(e); } public void linkLast(Object e) { final Node l = last; final Node newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; } public String toString() { return first.toString(); } } 下面是LinkedList的add(Object)方法的实现过程 ·测试LinkedList 【示例10】测试LinkedList public class TestList { public static void main(String[] args) { //创建线性顺序表 List list = new LinkedList(); //向末尾添加元素 list.add("11111"); list.add("aaaaa"); list.add("bbbbb"); list.add("33333"); list.add("22222"); list.add(3, "AAAAA"); //进行各种操作验证添加 System.out
Spark分布式计算框架之Stage一、Spark算子分类? Spark分布式计算框架之Stage 一、Spark算子分类? 二、Spark RDD的宽窄依赖 三、Spark中Stage pipeline 计算模式 四、Spark计算模式的代码验证 Spark 分布式计算框架之Stage 一、Spark算子分类 Spark中的算子分为三类: 1. Transformation 类算子 Transformation类算子又叫转换算子,在Spark中负责数据的转换,但是由于Spark中迭代器模式处理数据,具备懒执行的特点。 Transformation类算子举例:flatMap,map,reduceByKey等。 2. Action类算子 Action类算子又叫行动算子,是用来触发Transformation类算子执行的。在Spark中每当有一个Action算子就会有一个job。 Action算子举例:count,foreach。 1. 持久化类算子 持久化算子在Spark中是对RDD进行持久化的,算子举例:cache,persist,checkpoint。 一、Spark RDD的宽窄依赖 RDD:Resilient Distributed Dataset,弹性分布式数据集。由于Spark在处理数据过程中,数据有可能是在同一个节点上进行处理,也有可能在不同的节点上进行处理,形成了RDD至今的宽窄依赖,RDD的宽依赖是会产生shuffle的。 RDD之间是有宽窄依赖之分的,如上图所示,RDD1、RDD2、RDD3三个RDD之间进行转换时,数据都是由上一个RDD的某个分区全部流转到下个RDD的一个分区中,这种关系就是RDD的窄依赖。 当RDD3生成RDD4时,RDD3中某个分区中的数据被分往了RDD4中多个分区中,这种依赖关系就是宽依赖,这个过程在节点之间是由数据传输的,也就是shuffle过程。也就是说宽依赖处理数据时一定伴随shuffle的产生。 以上RDD设置这种宽窄依赖的处理方式是为了更好的并行化处理数据同时更好的适应各种数据处理场景。 上图是在MR中shuffle的过程,在Spark中,shuffle的过程与MR中shuffle的过程类似。由于shuffle原因所以有些RDD之间的依赖是shuffle依赖。 如果父RDD与子RDD之间的依赖关系是一对一 ,这就是窄依赖。 如果父RDD与子RDD之间的依赖关系是多对一,这就是宽依赖。 三、Spark中stage pipeline计算模式 以上解释了RDD的宽窄依赖关系,在Spark底层处理数据时,会生成对应的stage阶段,当RDD依赖关系有一个宽衣关系时,就会有一个Stage阶段的产生,因为当前这个Stage中的数据是没有数据合并的过程,只是单纯的对数据并行的处理过程。当宽依赖关系产生下一个RDD时,会生成下一个Stage,下一个Stage中处理数据的来源就是上一个Stage处理数据的结果,Stage2再次数据数据时,会将相同类型的数据从不同的节点上经过shuffle聚合在一起,然后继续处理,这样达到大数据处理数据的聚合统计过程。 那么在每个Stage处理数据时,每个Stage是有并行度的,这里的并行度由组成Stage的RDD的block个数决定,一般是Stage中最后一个RDD的partition个数决定。这样,每个并行度的task都会被发往对应的数据源头节点上处理数据,以达到并行处理数据的目的。以上Spark这种处理数据的模型就叫做pipeline管道计算模式,其实形成Stage这种pipeline管道计算模式的归根结底的原因是底层迭代器这种处理数据的方式,处理数据量大的场景时Spark不需要更多的内存,只需要保证到当前task需要的内存即可。 四、Spark计算模式的代码验证
这里推荐10本编程的图书,觉得搭配视频学习会更好一些有需要的 这里推荐10本编程的图书,觉得搭配视频学习会更好一些 有需要的伙伴们可以在评论区给我留言,或者私信我  好书,尤其适合当代程序员读。近几年软件开发的门槛降低了很多,好多公司都因为初级程序员的存在累计了一大批shit一样的代码,重构也讲技巧和原则,不是单纯地删除重写。看了几页就有收获,推荐给各位开发同行没事儿读读,肯定有启发。  我觉得这本就是指导程序员从低等级向高等级转变的必要圣经。每一篇幅都需要仔细阅读,深入思考,作者多年的经验可以给我们在实际项目中处理给予很大的帮助。通过在实践中,摸索,探讨,最终都会发现很多问题都能在这本书找到最好的指导。  随着技术的发展,每一代人都在做上一代人觉得很浪费的事情。浪费程序员的时间,而不是机器的时间,才是真正的无效率。随着计算机速度越来越快,这会越来越明显,所以,现在被认为缺点是运行速度慢的语言,将来会有更大的发展空间,毕竟从哲学角度上将,它的慢必然伴随着其他方面的优势。 要更好的创造财富,你做的事情需要两点保证:可测量性,可放大性。硅谷的诀窍,可测量性来自小团队,可放大性来自开发新技术。 未来的人类生活不仅是人与人的互动,而是越来越多的与计算机互动,所以必须理解计算机,其关键就是理解计算机背后的人,即设计计算机的人——程序员,而最伟大的程序员就是黑客。 书中个人喜好的话,引人深思。  Jon Bentley 世界著名计算机科学家,被誉为影响算法发展的十位大师之一。 阅读这本书,一定不要泛泛而读,每一章都值得你用一个月的时间来思考。不要放过书上任何一个例子任何一个习题,在看答案之前,至少让自己有一天的时间来思考这个问题并得出自己的方案,再去和书上的解决方案比较,才能更深刻地理解这个问题,才能找到自己和大师的差距  软件构建的核心就是管理复杂度。 代码首先是为了人而写的,不是为了机器。 精辟精辟!  相当不错的国内原创图书.很好的一本书,重要的是有详实的例子,读起来不生涩 ~ 关于虚拟机内存、gc、调优、类加载、class文件格式、编译优化等都值得一读  Donald E. Knuth,1938年1月10日出生于美国明尼苏达州的米尔沃基,著名计算机科学家,算法与程序设计技术的先驱,斯坦福大学计算机系荣誉退休教授,计算机排版系统TEX和 METAFONT字体系统的发明人,最年轻的图灵奖得主。他在计算机科学及数学领域出版和发表了多部具有广泛影响的著作和论文。 他获得了很多奖项和荣誉: 1971年获首届美国计算机协会(ACM) Grace Murray Hopper奖 1973年当选为美国科学艺术学院院士 1974年获美国计算机协会图灵奖 1975年当选为美国国家科学院院士,同年荣获美国数学协会(MAA)福特奖(Lester R. Ford Award) 1979年获卡特总统颁发的美国科学奖 1981年当选为美国工程院院士 1982年获计算机先锋奖(Computer Pioneer Award) 1982年成为IEEE荣誉会员 1986年荣获美国数学学会(AMS)斯蒂尔奖(Steele Award) 1988年获富兰克林奖章(Franklin Medal) 1994年获瑞典科学院Adelskold奖 1995年获IEEE冯·诺依曼奖 ......... 书籍太多,就不一一列举了
1 下一页