最新最热

2020 前端技术发展回顾

2020终究是一个不平凡的一年,我们经历了太多坎坷与磨炼。甚至受COVID-19疫情的影响,Chrome浏览器罕见的断更了,Chrome82就此缺席。但We生态依旧保持了欣欣向荣的活力,一大批新特性持续不断涌现出来。标准与协议ECMAScritES2020如期发布,此前进入Stage4的提案均被纳入正式规范。imort():用于动态加载模块;imort.meta:一个对象,用来携带模块相关的元信息;exort*aewModulefrom'ackage':一种新的聚合导出语法;新增可选链运算符?.:能够在属性访问、方法调用前检查其是否存在;新增空值合并操作符??:用来提供默认值,说明上下文是ull或udefied;新增BigIt基础数值类型:可以表示绝对值大于2^53-1的整数而无精度损失;新增Promie.allSettled():返回一个在所有给定的Promie已进入fullfilled或rejected状态的Promie,并带有一个对象数组,每个对象表示对应的Promie结果;新增Strig.rototye.matchAll:一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。与RegEx.rototye.exec的区别在于:如果要得到所有匹配项,需要正则表达式有/g标志,且多次调用.exec()才会得到所有匹配的结果,而matchAll只需要调用一次;新增gloalThi:用来解决浏览器、Node.j等不同环境下,全局对象名称不统一,获取全局对象比较麻烦的问题。CSS特性Flexox已经全面普及,垂直居中不再是前端「打工人」的烦恼丝。双飞翼、圣杯布局等各种Hack的手法也终究淹没在历史的长河之中。Flexox中也支持了[ga](htt://lik.zhihu.com/?target=htt%3A//develoer.mozilla.org/e-US/doc/We/CSS/ga)属性,可以非常方便的调节相邻元素的间距,主流浏览器均已支持;所有主流浏览器都支持了CSSGrid,同时也被更多人熟知和使用,Sugrid(子网格)在Firefox71中正式发布。Float、ilie-lock不再成为页面布局首选,CSS布局正在从一维向二维挺近;纵横比属性[aect-ratio](htt://lik.zhihu.com/?target=htt%3A//develoer.mozilla.org/e-US/doc/We/CSS/aect-ratio)已经在Chrome88中支持,通过它可以非常方便的实现元素的等比缩放;Firefox创新性的基于CSSGrid实现了瀑布流布局(grid-temlate-row:maory),并推动其进入规范,这将比JavaScrit方案拥有更好的性能;容器查询(CotaierQuerie)取得了实质性进展,Chrome正在快马加鞭的实现中。有了它响应式组件如虎添翼,可以根据容器大小来设置不同的样式;Chrome86和Firefox85支持了:focu-viile伪类,可以单独控制键盘的焦点样式,请停止使用*{outlie:oe},改用:focu:ot(:focu-viile){outlie:oe}:focu-viile{outlie:auto},这样既可以保证鼠标点击时没有焦点框,也保留了键盘Ta键操作的时候出现焦点框,使页面的无障碍性更加友好。技术领域数据来自TheStateofCSS2020处理器:三大预处理器(Sa、Le、Stylu)中,Sa满意度最高,其他两者相对较低,其中很大一部分人转投了后处理器PotCSS的阵营。Sa社区的LiSa宣布已弃用,不再支持新的功能的开发,LiSa和ode-a将在最大努力的基础上继续无限期维护,包括修复主要的错误和安全性问题,并保持与最新版本的Node.j相兼容;CSS框架层面:前有CSS-i-JS的持续追击,后有以「实用原子类」为代表的TailwidCSS异军突起,迫使我们重新思考CSS语义化类名的真谛。传统CSS框架中,用户继续使用Boottra的意愿明显下降,Pure.CSS欢迎度不减;CSS-i-JS:CSSModule和StyledComoet继续保持在第一阵营;Liter:Stylelit依然是StyleLit领域的领头羊。Prettier作为「全能」的格式化工具,支持原生CSS、SCSS、Le三种语法,是开发者格式化样式的不二之选,搭配GitHook使用,妙不可言。端技术WeAPIChrome87开始,可以在JavaScrit层面控制摄像头的平移、倾斜和缩放了;WeNFC在Chrome81开始进入初始试用计划;Safari14已支持WeP图片格式,至此,四大主流浏览器(Chrome、Firefox、Edge、Safari)已全部支持WeP;Safari14已支持We端通过WeAutheticatioAPI调用FaceID和TouchID验证用户;优化高DOM渲染压力场景的DilayLockig(展现锁定)提案再次更新;下一代图片格式AVIF(AV1ImageFileFormat)已经来了,此格式比JPEG小50%左右、比WeP小20%左右,相关性能跑分见此,目前Chrome85、Firefox77已支持;HTMLeterkeyhit属性已在Chrome77、Safari13.1得到支持(Firefox支持私有的mozactiohit属性),该属性可以使移动设备键盘中的eter键根据情景展现为不同的文案和样式;W3C沉浸式We工作组发布WeXR手势输入模块Level1规范的首个公开工作草案,该模块具有追踪关节手势的功能,可用于在VR场景中识别手部关节姿势或渲染手势模型。安全隐私保护得到完善2020年是欧盟通用数据保护协议GDPR强制生效的第三年,也是熔断Meltdow与幽灵Sectre漏洞发生的第三年。在2020年,各大浏览器安全和隐私保护策略得到了很大的进展。下线有安全隐患的支持:TLS1.0amTLS1.1已在Chrome84+、Firefox74+、Safari13.1+中下线:FTP已在Safari14+、Chrome87+中下线,将在Firefox将来版本中下线;Flah已在Safari14+中下线,将在Chrome88+、Firefox85+中下线;跨站隔离优化:2018年初,由于Sectre漏洞的暴露,高精度定时器和SharedMemoryAPI被禁用,为预防相关漏洞,浏览器需要保证不同站点在不同进程,相互隔离;为了保证跨站进程隔离,Cro-Origi-Oeer-Policy和Cro-Origi-Emedder-Policy返回头被设计出来。当它们被服务端正确返回时,Firefox79+和Chrome88+对SharedMemoryAPI的支持将重新打开;跨站嗅探预防:在Safari13.1+中,第三方Cookie完全被禁用,JavaScrit可写的存储最多保留一周;在Safari14+中,跨域资源的Cookie完全被禁用,除非经由StorageAcceAPI显式获取用户的同意;第三方CNAME的域名Cookie最多可设置7天有效期;在Firefox79+中,新版智能跨站嗅探预防(ETP2.0)上线,将每24小时清除被判定为跨站嗅探的相关Cookie设置;缓存粒度优化:Chrome85+,HTTP缓存采用更细粒度的键(ETLD+1);Firefox将在85后实现同粒度的缓存键;Safari12.1+实现了顶部widow域名+URL的键控制机制;新的缓存机制隔离了iframe内外的跨域请求,能有效规避站点访问嗅探、跨站搜索攻击、跨站访问跟踪等隐私问题;其他安全策略:Chrome83+支持了TrutedTye以预防基于DOM的XSS;Chrome80+全量了SameSiteCookie默认值SameSite=Lax,此举可以提升站点安全性,从源头防御大量的CSRF漏洞;Firefox76+中使用locatio.href或ltmetahttequiv=“refreh”gt等方法导航到未知协议的操作将被阻止。框架和解决方案框架2020年React没有什么全新的概念,ReactHook在社区从广受关注变成了实际落地;大家等待已久的Vue3.0正式发布,在保留自身特色的同时也从React中汲取养分。React发布了17版本,号称一个没有新特性的大版本更新,提供多版本React共存的能力;经过持续两年的努力,2600+个提交之后,Vue3.0发布了代号OePiece的正式版:重新划分了模块:可以减少近半运行时大小。拆出的一些独立包也可复用在更多场景:AST转换、自定义渲染器(如小程序)、响应式系统抽离出来独立使用;新的ComoitioAPI:在保留原有基于对象的API同时提出的新的API,以达到类似ReactHook式的逻辑重用;性能提升:与Vue2相比,打包后文件尺寸(tree-hakig时减少了41%)、初始渲染(快了55%)、更新(快了133%)和内存使用(少了54%)方面都有显著的性能提升,模板编译时优化对性能提升有很大贡献;更好的TyeScrit集成:Vue3由TyeScrit写成,新的ComoitioAPI能很好支持TS类型推断,官方的VSCode扩展Vetur支持了模板中的类型检查,Vue3更是完整支持了tx。Weack又有更多对手出于对Weack的爱恨交加,大家纷纷用更新颖的想法或更激进的技术造起了全新的开发工具链,也促使Weack加快自我迭代的步伐。Weack5.0正式发布,这是时隔2年半的大版本更新,通过持久缓存提高构建性能,通过更好的TreeShakig和代码生成来降低打包大小;vite作为Vue作者的新项目快速引来关注,它基于浏览器原生ESimort,因而有更快的冷启动和热更新,整体速度与模块数量无关。没有打包的过程,源码直接传输给浏览器使用原生的ltcritmodulegt语法进行引入,开发服务器拦截请求和对需要转换的代码进行转换,实现了真正的按需编译。生产环境提供了viteuild脚本进行打包,它基于rollu进行打包;基于原生ESModule(ESM)的现代打包工具Sowack2.0发布,其启动时间不到50毫秒,可以在大型项目中保持快速运行,内置对TyeScrit,JSX,CSSModule的支持,可与React,Preact,Vue,Svelte等前端开发框架结合使用;Bael作者SeatiaMcKezie推出了JavaScrit工具链Rome,包含编译器、代码风格检查、格式化、打包、测试框架等内容,亮点在于零第三方依赖并简化API配置。

这些一行 JS 实现功能的代码,让你看起来像一个前端专家

加载中...
JavaScrit可以做很多神奇的事情!从复杂的框架到处理API,有太多的东西需要学习。但是,它也能让你只用一行代码就能做一些了不起的事情。看看这13句JavaScrit单行代码,会让你看起来像个专家!1.获取一个随机布尔值(true/fale)这个函数使用Math.radom()方法返回一个布尔值(true或fale)。Math.radom将在0和1之间创建一个随机数,之后我们检查它是否高于或低于0.5。这意味着得到真或假的几率是50%/50%。cotradomBoolea=()=gtMath.radom()gt=0.5coole.log(radomBoolea())//Reult:a50/50chageoreturigtrueoffale2.检查日期是否为工作日使用这个方法,你就可以检查函数参数是工作日还是周末。cotiWeekday=(date)=gtdate.getDay()%6!==0coole.log(iWeekday(ewDate(2021,0,11)))//Reult:true(Moday)coole.log(iWeekday(ewDate(2021,0,10)))//Reult:fale(Suday)3.反转字符串有几种不同的方法来反转一个字符串。以下代码是最简单的方式之一。cotrevere=tr=gttr.lit('').revere().joi('')revere('helloworld')//Reult:'dlrowolleh'4.检查当前Ta页是否在前台我们可以通过使用documet.hidde属性来检查当前标签页是否在前台中cotiBrowerTaIView=()=gtdocumet.hiddeiBrowerTaIView()//Reult:returtrueorfaledeedigoiftaiiview/focu5.检查数字是否为奇数最简单的方式是通过使用模数运算符(%)来解决。如果你对它不太熟悉,这里是tackoverflow上的一个很好的图解。cotiEve=um=gtum%2===0coole.log(iEve(2))//Reult:truecoole.log(iEve(3))//Reult:fale6.从日期中获取时间通过使用toTimeStrig()方法,在正确的位置对字符串进行切片,我们可以从提供的日期中获取时间或者当前时间。cottimeFromDate=date=gtdate.toTimeStrig().lice(0,8)coole.log(timeFromDate(ewDate(2021,0,10,17,30,0)))//Reult:quot17:30:00quotcoole.log(timeFromDate(ewDate()))//Reult:willlogthecurrettime7.保留小数点(非四舍五入)使用Math.ow()方法,我们可以将一个数字截断到某个小数点。cottoFixed=(,fixed)=gt~~(Math.ow(10,fixed)*)/Math.ow(10,fixed)//ExamletoFixed(25.198726354,1)//25.1toFixed(25.198726354,2)//25.19toFixed(25.198726354,3)//25.198toFixed(25.198726354,4)//25.1987toFixed(25.198726354,5)//25.19872toFixed(25.198726354,6)//25.1987268.检查元素当前是否为聚焦状态cotelemetIIFocu=(el)=gt(el===documet.activeElemet)elemetIIFocu(ayElemet)//Reult:willreturtrueififocu,faleifotifocu9.检查浏览器是否支持触摸事件cottouchSuorted=()=gt{('otouchtart'iwidow||widow.DocumetTouchamamdocumetitaceofwidow.DocumetTouch)}coole.log(touchSuorted())//Reult:willreturtrueiftouchevetareuorted,faleifot10.检查当前用户是否为苹果设备我们可以使用avigator.latform来检查当前用户是否为苹果设备。cotiAleDevice=/Mac|iPod|iPhoe|iPad/.tet(avigator.latform)coole.log(iAleDevice)//Reult:willreturtrueifuerioaAledevice11.滚动到页面顶部widow.crollTo()方法会取一个x和y坐标来进行滚动。如果我们将这些坐标设置为零,就可以滚动到页面的顶部。注意:IE不支持crollTo()方法。cotgoToTo=()=gtwidow.crollTo(0,0)goToTo()//Reult:willcrolltherowertothetooftheage12.获取所有参数平均值我们可以使用reduce方法来获得函数参数的平均值。cotaverage=(...arg)=gtarg.reduce((a,)=gta+)/arg.legthaverage(1,2,3,4)//Reult:2.513.转换华氏度/摄氏度。(这个应该很少在国内用到吧)处理温度有时会让人感到困惑。这2个功能将帮助你将华氏温度转换为摄氏温度,反之亦然。cotceliuToFahreheit=(celiu)=gtceliu*9/5+32cotfahreheitToCeliu=(fahreheit)=gt(fahreheit-32)*5/9//ExamleceliuToFahreheit(15)//59celiuToFahreheit(0)//32celiuToFahreheit(-20)//-4fahreheitToCeliu(59)//15fahreheitToCeliu(32)//0谢谢你的阅读!希望你今天能学到一些新的东西。

Webpack 性能优化

加载中...
在这里,我不会浪费篇幅给大家讲如何写配置文件。如果你想学习这方面的内容,那么完全可以去官网学习。在这部分的内容中,我们会聚焦于以下两个知识点,并且每一个知识点都属于高频考点:有哪些方式可以减少Weack的打包时间有哪些方式可以让Weack打出来的包更小减少Weack打包时间优化Loader对于Loader来说,影响打包效率首当其冲必属Bael了。因为Bael会将代码转为字符串生成AST,然后对AST继续进行转变最后再生成新的代码,项目越大,转换代码越多,效率就越低。当然了,我们是有办法优化的。首先我们可以优化Loader的文件搜索范围module.exort={module:{rule:[{//j文件才使用aeltet:/\.j$/,loader:'ael-loader',//只在rc文件夹下查找iclude:[reolve('rc')],//不会去查找的路径exclude:/ode_module/}]}}对于Bael来说,我们肯定是希望只作用在JS代码上的,然后ode_module中使用的代码都是编译过的,所以我们也完全没有必要再去处理一遍。当然这样做还不够,我们还可以将Bael编译过的文件缓存起来,下次只需要编译更改过的代码文件即可,这样可以大幅度加快打包时间loader:'ael-loader?cacheDirectory=true'HayPack受限于Node是单线程运行的,所以Weack在打包的过程中也是单线程的,特别是在执行Loader的时候,长时间编译的任务很多,这样就会导致等待的情况。HayPack可以将Loader的同步执行转换为并行的,这样就能充分利用系统资源来加快打包效率了module:{loader:[{tet:/\.j$/,iclude:[reolve('rc')],exclude:/ode_module/,//id后面的内容对应下面loader:'hayack/loader?id=hayael'}]},lugi:[ewHayPack({id:'hayael',loader:['ael-loader?cacheDirectory'],//开启4个线程thread:4})]DllPlugiDllPlugi可以将特定的类库提前打包然后引入。这种方式可以极大的减少打包类库的次数,只有当类库更新版本才有需要重新打包,并且也实现了将公共代码抽离成单独文件的优化方案。接下来我们就来学习如何使用DllPlugi//单独配置在一个文件中//weack.dll.cof.jcotath=require('ath')cotweack=require('weack')module.exort={etry:{//想统一打包的类库vedor:['react']},outut:{ath:ath.joi(__dirame,'dit'),fileame:'[ame].dll.j',lirary:'[ame]-[hah]'},lugi:[ewweack.DllPlugi({//ame必须和outut.lirary一致ame:'[ame]-[hah]',//该属性需要与DllReferecePlugi中一致cotext:__dirame,ath:ath.joi(__dirame,'dit','[ame]-maifet.jo')})]}然后我们需要执行这个配置文件生成依赖文件,接下来我们需要使用DllReferecePlugi将依赖文件引入项目中//weack.cof.jmodule.exort={//...省略其他配置lugi:[ewweack.DllReferecePlugi({cotext:__dirame,//maifet就是之前打包出来的jo文件maifet:require('./dit/vedor-maifet.jo'),})]}ltacla=quotlake-achorquottyle=quotto:9xquotgtltacla=quotlake-achor-uttolake-icolake-ico-h3quotgtlt/agtlt/agt代码压缩在Weack3中,我们一般使用UglifyJS来压缩代码,但是这个是单线程运行的,为了加快效率,我们可以使用weack-arallel-uglify-lugi来并行运行UglifyJS,从而提高效率。在Weack4中,我们就不需要以上这些操作了,只需要将mode设置为roductio就可以默认开启以上功能。代码压缩也是我们必做的性能优化方案,当然我们不止可以压缩JS代码,还可以压缩HTML、CSS代码,并且在压缩JS代码的过程中,我们还可以通过配置实现比如删除coole.log这类代码的功能。一些小的优化点我们还可以通过一些小的优化点来加快打包速度reolve.exteio:用来表明文件后缀列表,默认查找顺序是['.j','.jo'],如果你的导入文件没有添加后缀就会按照这个顺序查找文件。我们应该尽可能减少后缀列表长度,然后将出现频率高的后缀排在前面reolve.alia:可以通过别名的方式来映射一个路径,能让Weack更快找到路径module.oPare:如果你确定一个文件下没有其他依赖,就可以使用该属性让Weack不扫描该文件,这种方式对于大型的类库很有帮助减少Weack打包后的文件体积注意:该内容也属于性能优化领域。按需加载想必大家在开发SPA项目的时候,项目中都会存在十几甚至更多的路由页面。如果我们将这些页面全部打包进一个JS文件的话,虽然将多个请求合并了,但是同样也加载了很多并不需要的代码,耗费了更长的时间。那么为了首页能更快地呈现给用户,我们肯定是希望首页能加载的文件体积越小越好,这时候我们就可以使用按需加载,将每个路由页面单独打包为一个文件。当然不仅仅路由可以按需加载,对于loadah这种大型类库同样可以使用这个功能。按需加载的代码实现这里就不详细展开了,因为鉴于用的框架不同,实现起来都是不一样的。当然了,虽然他们的用法可能不同,但是底层的机制都是一样的。都是当使用的时候再去下载对应文件,返回一个Promie,当Promie成功以后去执行回调。ScoeHoitigScoeHoitig会分析出模块之间的依赖关系,尽可能的把打包出来的模块合并到一个函数中去。比如我们希望打包两个文件//tet.jexortcota=1//idex.jimort{a}from'./tet.j'对于这种情况,我们打包出来的代码会类似这样[/*0*/fuctio(module,exort,require){//...},/*1*/fuctio(module,exort,require){//...}]但是如果我们使用ScoeHoitig的话,代码就会尽可能的合并到一个函数中去,也就变成了这样的类似代码[/*0*/fuctio(module,exort,require){//...}]这样的打包方式生成的代码明显比之前的少多了。如果在Weack4中你希望开启这个功能,只需要启用otimizatio.cocateateModule就可以了。module.exort={otimizatio:{cocateateModule:true}}TreeShakigTreeShakig可以实现删除项目中未被引用的代码,比如//tet.jexortcota=1exortcot=2//idex.jimort{a}from'./tet.j'对于以上情况,tet文件中的变量如果没有在项目中使用到的话,就不会被打包到文件中。如果你使用Weack4的话,开启生产环境就会自动启动这个优化功能。小结在这一章节中,我们学习了如何使用Weack去进行性能优化以及如何减少打包时间。Weack的版本更新很快,各个版本之间实现优化的方式可能都会有区别,所以我没有使用过多的代码去展示如何实现一个功能。这里重点是学习到我们可以通过什么方式去优化,具体的代码实现可以查找具体版本对应的代码即可。

JavaScript之深入理解this

加载中...
此文参考MDN_thi写成定义thi是函数运行时自动生成的内部对象,即调用函数的那个对象。(不一定很准确的定义,但还算通俗易懂)在大多数情况下,thi的值由函数调用方式决定,它不能在执行期间赋值来设置,它在每次执行下可能都有不同的值。全局执行环境(outidefuctio)在全局执行环境中,thi一直指向全局对象(gloaloject),不管是在严格模式还是在非严格模式中。代码1coole.log(thi.documet===documet)//true//在浏览器中,widow对象也就是全局对象(gloaloject)coole.log(thi===widow)//truethi.a=37coole.log(widow.a)//37ltacla=quotcoy-code-tquotgt复制代码lt/agt函数执行环境(iidefuctio)在函数执行环境中,thi的值取决于函数的调用方式。而函数的调用方式主要有4种:函数直接调用对象方法调用构造函数调用call/aly/id箭头函数(ES6)函数直接调用下面的代码在非严格模式执行时,thi的值会指向全局对象;而在严格模式中,thi的值将会默认为udefied。代码2/*非严格模式*/fuctiof1(){returthi}coole.log(f1()===widow)//true//iodecoole.log(f1()===gloal)//true/*严格模式*/fuctiof2(){'uetrict'returthi}coole.log(f1()===udefied)//truecall/aly/id改变thi的指向call/alycall和aly的用法很像,只是后面参数的传入形式不同。代码3fuctioadd(c,d){returthi.a+thi.+c+d}varo={a:1,:3}//call的第一个参数是对象,也就是thi的指向对象。后面的参数就是函数argumet对象的成员add.call(o,5,7)//1+3+5+7=16//call的第一个参数是对象,也就是thi的指向对象。后面的参数是数组,数组里的成员也就是函数argumet对象成员add.aly(o,[10,20])//1+3+10+20=34使用call和aly时需要注意的是,当传入的第一个参数的值不是对象时,JavaScrit会尝试使用ToOject操作将其转化为对象。代码4fuctioar(){coole.log(Oject.rototye.toStrig.call(thi))}ar.call(7)//[ojectNumer]ltacla=quotcoy-code-tquotgt复制代码lt/agtid方法ECMAScrit5引入了Fuctio.rototye.id。调用f.id(omeOject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,thi将永久地被绑定到了id的第一个参数,无论这个函数是如何被调用的。代码5fuctiof(){returthi.a}varg=f.id({a:'azerty'})//生成一个绑定函数gcoole.log(g())//azertyvaro={a:10,f:f,g:g}coole.log(o.f(),o.g())//10,azerty//需要注意的是,绑定函数不可以再idvarh=g.id({a:'foo'})coole.log(h())//azerty,不会变成foo对象方法调用当以对象里的方法的方式调用函数时,它们的thi是调用该函数的对象.下面的例子中,当o.f()被调用时,函数内的thi将绑定到o对象。varro=36varo={ro:37,ar:fuctio(){returthi.ro}}coole.log(o.ar())//37构造函数调用代码6fuctioPero(ame,age){thi.ame=amethi.age=agethi.itroduce=fuctio(){coole.log('Myamei'+thi.ame+',I\'m'+thi.age)}}varJoeh=ewPero('Joeh',19)Joeh.itroduce()//quotMyameiJoeh,I'm19quot由上述代码可以清晰的看到thi与被新创建的对象绑定了。注意:当构造器返回的默认值是一个thi引用的对象时,可以手动设置返回其他的对象,如果返回值不是一个对象,返回thi。(这句话看起来比较难理解,我们看下一个例子)。代码7fuctioF2(){thi.a=9//deadcoderetur{a:10}}varo=ewF2()coole.log(o.a)//10这个例子说明了当构造函数返回的是一个对象的话,此时thi的值会变成此时返回的对象。‘thi.a=9’成了僵尸代码。箭头函数在箭头函数(Arrowfuctio)中,thi的值是封闭执行环境决定的。在全局环境中,那么被赋值为全局对象。vargloalOject=thivarfoo=(()=amgtthi)coole.log(foo()===gloalOject)//true更重要的是它与其他情况不同的是,不管函数如何调用,上面thi的值一直都是全局对象。call/id也不能改变它的值。代码8//作为对象方法被调用varoj={foo:foo}coole.log(oj.foo()===gloalOject)//true//尝试用call改变thi的值coole.log(foo.call(oj)===gloalOject)//true//thi的值并未变成oj//尝试用id改变thi的值foo=foo.id(oj)coole.log(foo()===gloalOject)//true案例本文知识点都看完了。让我们看几个案例,检查自己的掌握情况。例1varro=36varo={ro:37,ar1:fuctio(){fuctiofoo1(){returthi.ro}returfoo1},ar2:fuctio(){varfoo2=(()=amgtthi.ro)//ES6箭头函数returfoo2}}coole.log('reult1:'+o.ar1()())//reult1?coole.log('reult2:'+o.ar2()())//reult2?varf2=o.ar2coole.log('reult3:'+f2()())//reult3?先揭晓答案:例1reult1=36,reult2=37,reult3=36。我的理解是,在reult1中,o.ar1()执行导致foo函数retur到了全局环境中,然后执行就变成了在全局中执行,所以得到的是全局中36的值。reult2呢?因为thi在箭头函数中。它的值不会改变。所以thi仍指向o。那为什么reult3又重新变了呢?因为此时varf2=o.ar2相当于重新定义了一个函数,而thi的值当然也就变为了全局对象。//相当于这样varf2=fuctio(){fuctiofoo1(){returthi.ro}returfoo1}f2()()例2fuctioum(a,){retura+}varo={um:1,f:fuctio(){fuctiohadle(){returthi.um=um(thi.um,thi.um)}hadle()}}coole.log('reult:'+o.f())//reult?同样先揭晓答案:reult=udefied,用控制台可以看到此时thi指向widow,而不是o。这是个比较容易掉进去的坑(一般认为是当初的语言设计错误,被人诟病不少)。看似函数是由对象方法调用的,其实细心的话,我们可以看到。hadle函数的执行,前面的没有对象的。这种情况下,thi指向全局对象。解决办法也很简单。//1、取消hadle函数的定义,直接在对象的方法中使用thif2:fuctio(){thi.value=um(thi.value,thi.value)//2},///2、使用变量保存外部函数的thi。f3:fuctio(){varthat=thi//that==ofuctiohadle(){that.value=add(that.value,that.value)}hadle()}参考文章:Javacrit中thi与闭包学习笔记lt/ligt理解JS中的thilt/ligt

这一次,彻底搞懂 —— 构造函数和new

在此之前先问自己几个问题:什么是构造函数?和普通函数的区别?所有函数都可以被ew吗?ew操作符做了什么?如何自己实现一个ew?ew.target知道吗?如果不太清楚,懵懵懂懂的话,不要慌乱,不妨往下阅读~本篇文章就是着重解决这些问题的。相信认真看完之后,你定会对以上问题有所收获~构造函数对于使用过基于类的语言(如Java或C++)的开发人员来说,JavaScrit有点令人困惑,因为它是动态的,并且本身不提供一个cla实现。(在ES2015/ES6中引入了cla关键字,但那只是语法糖,JavaScrit仍然是基于原型的)。即使我们模拟出的“类”,也只是一个函数对象。在Javacrit中的类和函数是无法区分的,我们似乎也只能定规范,比如构造函数模式,非严格规定:第一个字母大写的自定义函数就是构造函数。从技术上讲,任何函数(除了箭头函数)都可以用作构造器。即:箭头函数外的任何函数都可以通过ew来运行。构造器的主要目的——实现可重用的对象创建代码。构造函数在技术上是常规函数。不过有两个约定:它们的命名以大写字母开头。它们只能由quotewquot操作符来执行。这样的调用意味着在开始时创建了空的thi,并在最后返回填充了值的thi。ewew运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。一个简单的ew的例子:fuctioPero(){thi.ame='Jack'}var=ewPero()coole.log()//Pero{ame:quotJackquot}如果不使用ew关键词呢?fuctioPero(){thi.ame='Jack'}var=Pero()coole.log()//udefiedcoole.log(ame)//Jackcoole.log(.ame)//'ame'ofudefied我们发现,如果没有使用ew关键字调用构造函数,返回的是udefied,这是因为在全局环境中调用函数thi指向widow。那么当构造函数中`retur`一个对象会是什么样呢?fuctioPero(){thi.ame='Jack'retur{age:18}}var=ewPero()coole.log()//{age:18}coole.log(.ame)//udefiedcoole.log(.age)//18我们发现,当构造函数retur的是一个和thi无关的对象时,ew命令会直接返回这个新对象,而不是通过ew执行步骤生成的thi对象。注意:构造函数返回的必须是一个对象,如果不是对象,还是会按照ew的实现步骤,返回新生成的对象。例子:fuctioPero(){thi.ame='Jack'retur'tom'}var=ewPero()coole.log()//{ame:'Jack'}coole.log(.ame)//Jack因此我们总结一下:ew关键词执行后总是会返回一个对象,要么是实例对象,要么是retur语句指定的对象。ew做了什么?ew关键字会进行以下操作:创建一个空对象(即{})链接该对象(设置该对象的cotructor)到另一个对象把步骤1新创建的对象作为thi的上下文如果该对象没有返回对象,则返回thi高频面试题:手写ewfuctio_ew(Ctor,...arg){//ctor必须是个构造函数,而且不能是箭头函数if(!Ctor.rototye){throwewTyeError(`${Ctor}iotacotructor`)}//创建一个新的空对象letoj={}//将这个对象的原型和构造函数的原型关联oj.__roto__=Oject.create(Ctor.rototye)//将创建的对象作为上下文的thi,执行构造函数letre=Ctor.aly(oj,arg)letiOj=tyeofre==='oject'amamtyeofre!==ullletiFu=tyeofre==='fuctio'//返回这个新对象,即构造函数的retur的结果如果不是对象,就返回新生成的对象。returiOj||iFu?re:oj}ew.target在一个函数内部,我们可以使用ew.target属性来检查它是否被使用ew进行调用了。对于常规调用,它为空,对于使用ew的调用,则等于该函数:fuctioUer(){alert(ew.target)}//不带quotewquot:Uer()//udefied//带quotewquot:ewUer()//fuctioUer{...}它可以被用在函数内部,来判断该函数是被通过ew调用的“构造器模式”,还是没被通过ew调用的“常规模式”。我们也可以让ew调用和常规调用做相同的工作,像这样:fuctioUer(ame){if(!ew.target){//如果你没有通过ew运行我returewUer(ame)//……我会给你添加ew}thi.ame=ame}letjoh=Uer(quotJohquot)//将调用重定向到新用户alert(joh.ame)//Joh最后如有问题,请大佬指正~如有帮助,希望能够点赞收藏~参考资料:MDN的ew运算符现代JavaScrit教程火锅oy的手写ew

前端Javascript与Nodejs的异同

前言很多小伙伴学Node的时候,都没有好好认识她就开始疯狂追求,想一举拿下,直接在网上搜索Node实战,想知道她活好不好,想先用她建个简单博客练练手。JavaScrit和Nodej我相信很多入坑Nodej的人都是前端转过来的,但是局限于公司项目用不到Nodej,只能自学,有些重要且基础的东西就忽略了。下面我们说一下前端的Javacrit和Nodej。每个前端大虾都很了解JavaScrit,我们用它操作dom,用它写数据交互和页面效果,ut....请问你真的知道JavaScrit吗?我保证还有很多不知道JavaScrit=ECMAScrit+DOM+BOM。现在就可以知道了,前端的JavaScrit其实是由ECMAScrit、DOM、BOM组合而成。JavaScrit:ECMAScrit(语言基础,如:语法、数据类型结构以及一些内置对象)DOM(一些操作页面元素的方法)BOM(一些操作浏览器的方法)上面是JavaScrit的组成部分,那么Nodej呢?Nodej:ECMAScrit(语言基础,如:语法、数据类型结构以及一些内置对象)o(操作系统)file(文件系统)et(网络系统)dataae(数据库)分析:很容易看出,前端和后端的j相同点就是,他们的语言基础都是ECMAScrit,只是他们所扩展的东西不同,前端需要操作页面元素,于是扩展了DOM,也需要操作浏览器,于是就扩展了BOM。而服务端的j则也是基于ECMAScrit扩展出了服务端所需要的一些API,稍微了解后台的童鞋肯定知道,后台语音有操作系统的能力,于是扩展o,需要有操作文件的能力,于是扩展出file文件系统、需要操作网络,于是扩展出et网络系统,需要操作数据,于是要扩展出dataae的能力。这么一对比,相信很多小伙伴对odej更加了解了,原来前端和服务端的j如此相似,他们的基础是相同的,只是环境不同,导致他们扩展出来的东西不同而已。

10个JavaScript难点

为了保证可读性,本文采用意译而非直译,并且对示例代码进行了大量修改。另外,本文版权归原作者所有,翻译仅用于学习。1.立即执行函数立即执行函数,即ImmediatelyIvokedFuctioExreio(IIFE),正如它的名字,就是创建函数的同时立即执行。它没有绑定任何事件,也无需等待任何异步操作:(fuctio(){//代码//...})()fuctio(){…}是一个匿名函数,包围它的一对括号将其转换为一个表达式,紧跟其后的一对括号调用了这个函数。立即执行函数也可以理解为立即调用一个匿名函数。立即执行函数最常见的应用场景就是:将var变量的作用域限制于你们函数内,这样可以避免命名冲突。2.闭包对于闭包(cloure),当外部函数返回之后,内部函数依然可以访问外部函数的变量。fuctiof1(){varN=0//N是f1函数的局部变量fuctiof2()//f2是f1函数的内部函数,是闭包{N+=1//内部函数f2中使用了外部函数f1中的变量Ncoole.log(N)}returf2}varreult=f1()reult()//输出1reult()//输出2reult()//输出3代码中,外部函数f1只执行了一次,变量N设为0,并将内部函数f2赋值给了变量reult。由于外部函数f1已经执行完毕,其内部变量N应该在内存中被清除,然而事实并不是这样:我们每次调用reult的时候,发现变量N一直在内存中,并且在累加。为什么呢?这就是闭包的神奇之处了!3.使用闭包定义私有变量通常,JavaScrit开发者使用下划线作为私有变量的前缀。但是实际上,这些变量依然可以被访问和修改,并非真正的私有变量。这时,使用闭包可以定义真正的私有变量:fuctioProduct(){varamethi.etName=fuctio(value){ame=value}thi.getName=fuctio(){returame}}var=ewProduct().etName(quotFudeugquot)coole.log(.ame)//输出udefiedcoole.log(.getName())//输出Fudeug代码中,对象的的ame属性为私有属性,使用.ame不能直接访问。4.rototye每个JavaScrit构造函数都有一个rototye属性,用于设置所有实例对象需要共享的属性和方法。rototye属性不能列举。JavaScrit仅支持通过rototye属性进行继承属性和方法。fuctioRectagle(x,y){thi._legth=xthi._readth=y}Rectagle.rototye.getDimeio=fuctio(){retur{legth:thi._legth,readth:thi._readth}}varx=ewRectagle(3,4)vary=ewRectagle(4,3)coole.log(x.getDimeio())//{legth:3,readth:4}coole.log(y.getDimeio())//{legth:4,readth:3}代码中,x和y都是构造函数Rectagle创建的对象实例,它们通过rototye继承了getDimeio方法。5.模块化JavaScrit并非模块化编程语言,至少ES6落地之前都不是。然而对于一个复杂的We应用,模块化编程是一个最基本的要求。这时,可以使用立即执行函数来实现模块化,正如很多JS库比如jQuery以及我们Fudeug都是这样实现的。varmodule=(fuctio(){varN=5fuctiorit(x){coole.log(quotThereulti:quot+x)}fuctioadd(a){varx=a+Nrit(x)}retur{decritio:quotThiidecritioquot,add:add}})()coole.log(module.decritio)//输出quotthiidecritioquotmodule.add(5)//输出“Thereulti:10”所谓模块化,就是根据需要控制模块内属性与方法的可访问性,即私有或者公开。在代码中,module为一个独立的模块,N为其私有属性,rit为其私有方法,decritio为其公有属性,add为其共有方法。6.变量提升JavaScrit会将所有变量和函数声明移动到它的作用域的最前面,这就是所谓的变量提升(Hoitig)。也就是说,无论你在什么地方声明变量和函数,解释器都会将它们移动到作用域的最前面。因此我们可以先使用变量和函数,而后声明它们。但是,仅仅是变量声明被提升了,而变量赋值不会被提升。如果你不明白这一点,有时则会出错:coole.log(y)//输出udefiedy=2//初始化y上面的代码等价于下面的代码:vary//声明ycoole.log(y)//输出udefiedy=2//初始化y为了避免BUG,开发者应该在每个作用域开始时声明变量和函数。7.柯里化柯里化,即Curryig,可以是函数变得更加灵活。我们可以一次性传入多个参数调用它;也可以只传入一部分参数来调用它,让它返回一个函数去处理剩下的参数。varadd=fuctio(x){returfuctio(y){returx+y}}coole.log(add(1)(1))//输出2varadd1=add(1)coole.log(add1(1))//输出2varadd10=add(10)coole.log(add10(1))//输出11代码中,我们可以一次性传入2个1作为参数add(1)(1),也可以传入1个参数之后获取add1与add10函数,这样使用起来非常灵活。8.aly,call与id方法JavaScrit开发者有必要理解aly、call与id方法的不同点。它们的共同点是第一个参数都是thi,即函数运行时依赖的上下文。三者之中,call方法是最简单的,它等价于指定thi值调用函数:varuer={ame:quotRahulMhatrequot,whatIYourName:fuctio(){coole.log(thi.ame)}}uer.whatIYourName()//输出quotRahulMhatrequot,varuer2={ame:quotNehaSamatquot}uer.whatIYourName.call(uer2)//输出quotNehaSamatquotaly方法与call方法类似。两者唯一的不同点在于,aly方法使用数组指定参数,而call方法每个参数单独需要指定:aly(thiArg,[argArray])call(thiArg,arg1,arg2,…)varuer={greet:quotHello!quot,greetUer:fuctio(uerName){coole.log(thi.greet+quotquot+uerName)}}vargreet1={greet:quotHolaquot}uer.greetUer.call(greet1,quotRahulquot)//输出quotHolaRahulquotuer.greetUer.aly(greet1,[quotRahulquot])//输出quotHolaRahulquot使用id方法,可以为函数绑定thi值,然后作为一个新的函数返回:varuer={greet:quotHello!quot,greetUer:fuctio(uerName){coole.log(thi.greet+quotquot+uerName)}}vargreetHola=uer.greetUer.id({greet:quotHolaquot})vargreetBojour=uer.greetUer.id({greet:quotBojourquot})greetHola(quotRahulquot)//输出quotHolaRahulquotgreetBojour(quotRahulquot)//输出quotBojourRahulquot9.MemoizatioMemoizatio用于优化比较耗时的计算,通过将计算结果缓存到内存中,这样对于同样的输入值,下次只需要中内存中读取结果。fuctiomemoizeFuctio(fuc){varcache={}returfuctio(){varkey=argumet[0]if(cache[key]){returcache[key]}ele{varval=fuc.aly(thi,argumet)cache[key]=valreturval}}}varfioacci=memoizeFuctio(fuctio(){retur(===0||===1)?:fioacci(-1)+fioacci(-2)})coole.log(fioacci(100))//输出354224848179262000000coole.log(fioacci(100))//输出354224848179262000000代码中,第2次计算**fioacci(100)**则只需要在内存中直接读取结果。10.函数重载所谓函数重载(methodoverloadig),就是函数名称一样,但是输入输出不一样。或者说,允许某个函数有各种不同输入,根据不同的输入,返回不同的结果。凭直觉,函数重载可以通过if…ele或者witch实现,这就不去管它了。jQuery之父JohReig提出了一个非常巧(ia)妙(tai)的方法,利用了闭包。从效果上来说,eole对象的fid方法允许3种不同的输入:0个参数时,返回所有人名;1个参数时,根据firtName查找人名并返回;2个参数时,根据完整的名称查找人名并返回。难点在于,eole.fid只能绑定一个函数,那它为何可以处理3种不同的输入呢?它不可能同时绑定3个函数fid0,fid1与fid2啊!这里的关键在于old属性。由addMethod函数的调用顺序可知,eole.fid最终绑定的是fid2函数。然而,在绑定fid2时,old为fid1;同理,绑定fid1时,old为fid0。3个函数fid0,fid1与fid2就这样通过闭包链接起来了。根据addMethod的逻辑,当f.legth与argumet.legth不匹配时,就会去调用old,直到匹配为止。fuctioaddMethod(oject,ame,f){varold=oject[ame]oject[ame]=fuctio(){//f.legth为函数定义时的参数个数//argumet.legth为函数调用时的参数个数if(f.legth===argumet.legth){returf.aly(thi,argumet)}eleif(tyeofold===quotfuctioquot){returold.aly(thi,argumet)}}}//不传参数时,返回所有amefuctiofid0(){returthi.ame}//传一个参数时,返回firtName匹配的amefuctiofid1(firtName){varreult=[]for(vari=0iamltthi.ame.legthi++){if(thi.ame[i].idexOf(firtName)===0){reult.uh(thi.ame[i])}}returreult}//传两个参数时,返回firtName和latName都匹配的amefuctiofid2(firtName,latName){varreult=[]for(vari=0iamltthi.ame.legthi++){if(thi.ame[i]===(firtName+quotquot+latName)){reult.uh(thi.ame[i])}}returreult}vareole={ame:[quotDeaEdwardquot,quotAlexRuellquot,quotDeaTomquot]}addMethod(eole,quotfidquot,fid0)addMethod(eole,quotfidquot,fid1)addMethod(eole,quotfidquot,fid2)coole.log(eole.fid())//输出[quotDeaEdwardquot,quotAlexRuellquot,quotDeaTomquot]coole.log(eole.fid(quotDeaquot))//输出[quotDeaEdwardquot,quotDeaTomquot]coole.log(eole.fid(quotDeaquot,quotEdwardquot))//输出[quotDeaEdwardquot]参考链接闭包–MDNJavaScrit闭包-块级作用域和私有变量Javacrit继承机制的设计思想–阮一峰变量提升–MDNJS函数式编程指南浅谈JavaScrit函数重载

这些 JS 中强大的操作符,总有几个你没听说过

加载中...
JS里的操作符大家每天都在使用,还有一些ES2020、ES2021新加的实用操作符,这些共同构成了JS灵活的语法生态。本文除介绍常用的操作符之外,还会介绍JS里一些不常用但是很强大的操作符,下面我们一起来看看吧~1.数值分割符_ES2021引入了数值分割符_,在数值组之间提供分隔,使一个长数值读起来更容易。Chrome已经提供了对数值分割符的支持,可以在浏览器里试起来。letumer=100_0000_0000_0000//0太多了不用数值分割符眼睛看花了coole.log(umer)//输出100000000000000此外,十进制的小数部分也可以使用数值分割符,二进制、十六进制里也可以使用数值分割符。0x11_1===0x111//true十六进制0.11_1===0.111//true十进制的小数011_1===0111//true二进制2.逗号运算符,什么,逗号也可以是运算符吗?是的,曾经看到这样一个简单的函数,将数组的第一项和第二项调换,并返回两项之和:fuctiorevere(arr){retur[arr[0],arr[1]]=[arr[1],arr[0]],arr[0]+arr[1]}cotlit=[1,2]revere(lit)//返回3,此时lit为[2,1]逗号操作符对它的每个操作数求值(从左到右),并返回最后一个操作数的值。exr1,exr2,exr3...会返回最后一个表达式exr3的结果,其他的表达式只会进行求值。3.零合并操作符??零合并操作符??是一个逻辑操作符,当左侧的操作数为ull或者udefied时,返回右侧操作数,否则返回左侧操作数。exr1??exr2空值合并操作符一般用来为常量提供默认值,保证常量不为ull或者udefied,以前一般使用||来做这件事variale=variale||'ar'。然而,由于||是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值。任何假值(0,'',NaN,ull,udefied)都不会被返回。这导致如果你使用0、''、NaN作为有效值,就会出现不可预料的后果。正因为||存在这样的问题,而??的出现就是解决了这些问题,??只会在左侧为udefied、ull时才返回后者,??可以理解为是||的完善解决方案。可以在浏览器中执行下面的代码感受一下:udefied||'default'//'default'ull||'default'//'default'fale||'default'//'default'0||'default'//'default'udefied??'default'//'default'ull??'default'//'default'fale??'default'//'fale'0??'default'//0另外在赋值的时候,可以运用赋值运算符的简写??=leta={:ull,c:10}a.??=20a.c??=20coole.log(a)//输出{:20,c:10}4.可选链操作符?.可选链操作符?.允许读取位于连接对象链深处的属性的值,而不必验证链中的每个引用是否有效。?.操作符的功能类似于.链式操作符,不同之处在于,在引用为ull或者udefied的情况下不会引起错误,该表达式短路返回值是udefied。当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。cotoj={a:'foo',:{c:'ar'}}coole.log(oj.?.c)//输出arcoole.log(oj.d?.c)//输出udefiedcoole.log(oj.fuc?.())//不报错,输出udefied以前可能会通过ojamamoj.aamamoj.a.来获取一个深度嵌套的子属性,现在可以直接oj?.a?.即可。可选链除了可以用在获取对象的属性,还可以用在数组的索引arr?.[idex],也可以用在函数的判断fuc?.(arg),当尝试调用一个可能不存在的方法时也可以使用可选链。调用一个对象上可能不存在的方法时(版本原因或者当前用户的设备不支持该功能的场景下),使用可选链可以使得表达式在函数不存在时返回udefied而不是直接抛异常。cotreult=omeIterface.cutomFuc?.()5.私有方法/属性在一个类里面可以给属性前面增加#私有标记的方式来标记为私有,除了属性可以被标记为私有外,getter/etter也可以标记为私有,方法也可以标为私有。claPero{getDec(){returthi.#ame+''+thi.#getAge()}#getAge(){returthi.#age}//私有方法get#ame(){retur'foo'}//私有访问器#age=23//私有属性}cota=ewPero()coole.log(a.age)//udefied直接访问不到coole.log(a.getDec())//foo236.位运算符gtgt与gtgtgt有符号右移操作符gtgt将第一个操作数向右移动指定的位数,多余的位移到右边被丢弃,高位补其符号位,正数补0,负数则补1。因为新的最左位与前一个最左位的值相同,所以符号位(最左位)不会改变。(0111gtgt1).toStrig(2)//quot11quot(-0111gtgt1).toStrig(2)//quot-100quot感觉跟直觉不一样正数的好理解,负数怎么理解呢,负数在计算机中存储是按照补码来存储的,补码的计算方式是取反加一,移位时将补码形式右移,最左边补符号位,移完之后再次取反加一求补码获得处理后的原码。-111//真值10000111//原码(高位的0无所谓,后面加不到)11111001//补码11111100//算数右移10000100//移位后求补码获得原码-100//移位后的真值一般我们用gtgt来将一个数除2,相当于先舍弃小数位然后进行一次Math.floor:10gtgt1//513gtgt1//6相当于13.9gtgt1//6-13gtgt1//-7相当于-13.9gtgt1//-7无符号右移操作符gtgtgt,将符号位作为二进制数据的一部分向右移动,高位始终补0,对于正整数和算数右移没有区别,对于负数来说由于符号位被补0,成为正数后就不用再求补码了,所以结果总是非负的。即便右移0个比特,结果也是非负的。(0111gtgtgt1).toStrig(2)//quot11quot(-0111gtgtgt1).toStrig(2)//quot1111111111111111111111111111100quot可以这样去理解-111//真值1000000000000000000000000000111//原码1111111111111111111111111111001//补码0111111111111111111111111111100//算数右移(由于右移后成为正数,就不要再求补码了)1073741820//移位后的真值左移运算符ltlt与之类似,左移很简单左边移除最高位,低位补0:(01111111111111111111111111111100ltlt1).toStrig(2)//quot-1000quot(01111111111111111111111111111100ltltlt1).toStrig(2)//quot-1000quotPS:JS里面没有无符号左移,而且其他语言比如JAVA也没有无符号左移。7.位运算符am与|.位运算符是按位进行运算,am与、|或、~非、^按位异或:am:1010|:1010~:1010^:1010011001100110----------------0010111001011100使用位运算符时会抛弃小数位,我们可以利用这个特性来给数字取整,比如给任意数字am上二进制的32个1,或者|上0,显而易见后者简单些。所以我们可以对一个数字|0来取整,负数也同样适用1.3|0//1-1.9|0//-1判断奇偶数除了常见的取余%2之外,也可以使用am1,来判断二进制数的最低位是不是1,这样除了最低位之外都被置0,取余的结果只剩最低位,是不是很巧妙。负数也同样适用:cotum=3!!(umam1)//true!!(um%2)//true8.双位运算符~~可以使用双位操作符来替代正数的Math.floor(),替代负数的Math.ceil()。双否定位操作符的优势在于它执行相同的操作运行速度更快。Math.floor(4.9)===4//true//简写为:~~4.9===4//true不过要注意,对正数来说~~运算结果与Math.floor()运算结果相同,而对于负数来说与Math.ceil()的运算结果相同:~~4.5//4Math.floor(4.5)//4Math.ceil(4.5)//5~~-4.5//-4Math.floor(-4.5)//-5Math.ceil(-4.5)//-4PS:注意~~(um/2)方式和umgtgt1在值为负数时的差别9.短路运算符amam与我们知道逻辑与amam与逻辑或||是短路运算符,短路运算符就是从左到右的运算中前者满足要求,就不再执行后者了。可以理解为:amam为取假运算,从左到右依次判断,如果遇到一个假值,就返回假值,以后不再执行,否则返回最后一个真值||为取真运算,从左到右依次判断,如果遇到一个真值,就返回真值,以后不再执行,否则返回最后一个假值letaram1=exr1amamexr2letaram2=exr1||exr2运算符示例说明amamexr1amamexr2如果exr1能转换成fale则返回exr1,否则返回exr2。因此,在Boolea环境中使用时,两个操作结果都为true时返回true,否则返回faleexr1||exr2如果exr1能转换成true则返回exr1,否则返回exr2。因此,在oolea环境(在if的条件判断中)中使用时,二者操作结果中只要有一个为true,返回true;二者操作结果都为fale时返回fale!!exr如果单个表达式能转换为true的话返回fale,否则返回true因此可以用来做很多有意思的事,比如给变量赋初值:letvariale1letvariale2=variale1||'foo'如果variale1是真值就直接返回了,后面短路就不会被返回了,如果为假值,则会返回后面的foo。也可以用来进行简单的判断,取代冗长的if语句:letvariale=aramamamaram.ro//有了可选链之后可以直接aram?.ro如果aram如果为真值则返回aram.ro属性,否则返回aram这个假值,这样在某些地方防止aram为udefied的时候还取其属性造成报错。10.void运算符void运算符对给定的表达式进行求值,然后返回udefied可以用来给在使用立即调用的函数表达式(IIFE)时,可以利用void运算符让JS引擎把一个fuctio关键字识别成函数表达式而不是函数声明。fuctioiife(){coole.log('foo')}()//报错,因为JS引擎把IIFE识别为了函数声明voidfuctioiife(){coole.log('foo')}()//正常调用~fuctioiife(){coole.log('foo')}()//也可以使用一个位操作符(fuctioiife(){coole.log('foo')})()//或者干脆用括号括起来表示为整体的表达式还可以用在箭头函数中避免传值泄漏,箭头函数,允许在函数体不使用括号来直接返回值。这个特性给用户带来了很多便利,但有时候也带来了不必要的麻烦,如果右侧调用了一个原本没有返回值的函数,其返回值改变后,会导致非预期的副作用。cotfuc=()=gtvoidcutomMethod()//特别是给一个事件或者回调函数传一个函数时安全起见,当不希望函数返回值是除了空值以外其他值,应该使用void来确保返回udefied,这样,当cutomMethod返回值发生改变时,也不会影响箭头函数的行为。11.其他常用操作符三元表达式:很简单了,大家经常用,exr?exr1:exr2如果exr为真值则返回exr1,否则返回exr2赋值运算符简写:加法赋值+=、减法赋值-=、乘法赋值*=、除法赋值/=、求幂赋值**=、按位或复制|=、按位与赋值am=、有符号按位右移赋值gtgt=、无符号按位右移赋值gtgtgt=、逻辑空赋值??=....求幂运算符:var1**var2相当于Math.ow,结果为var1的var2次方12.操作符优先级正因为有操作符优先级,所以variale=1,2的含义是将变量先赋值为1,再返回数字2,而不是变量赋值给1,2的返回值2,这是因为=运算符的优先级高于,逗号运算符。再比如表达式6-2*3===0amam1,-*===amam这四个运算符优先级最高的*先运算,然后-运算符结果为0,===运算符优先级高于amam而trueamam1的结果为1,所以这就是运算的结果。下面的表将运算符按照优先级的不同从高(20)到低(1)排列,但这个不是最新的,至少没包括可选链,建议参考这个表或者MDN。网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢迎留言指出,如果本文帮助到了你,别忘了点赞支持一下哦,你的点赞是我更新的最大动力!(收藏不点赞,都是耍流氓🤣)~参考文档:运算符优先级-JavaScrit|MDNJS中可以提升幸福度的小技巧4个未听说过的强大JavaScrit操作符聊聊JavaScrit中的二进制数

js判断浏览器设备与内核

加载中...
今天写一个下载页面的时候需要判断adroid或者io设备以及不同的浏览器打开方式。上网搜索了一下教程发现这个教程最清晰简单,并且很好用。在此记录一下,方便以后使用原理:根据avigator.uerAget返回值识别varu=avigator.uerAgetvariAdroid=u.idexOf('Adroid')gt-1||u.idexOf('Adr')gt-1//adroid终端variiOS=!!u.match(/\\(i\[^\]+(U)?CPU.+MacOSX/)//io终端判断访问终端//判断访问终端varrower={verio:fuctio(){varu=avigator.uerAget,a=avigator.aVerioretur{tridet:u.idexOf('Tridet')gt-1,//IE内核reto:u.idexOf('Preto')gt-1,//oera内核weKit:u.idexOf('AleWeKit')gt-1,//苹果、谷歌内核gecko:u.idexOf('Gecko')gt-1amamu.idexOf('KHTML')==-1,//火狐内核moile:!!u.match(/AleWeKit.\*Moile.\*/),//是否为移动终端io:!!u.match(/\\(i\[^\]+(U)?CPU.+MacOSX/),//io终端adroid:u.idexOf('Adroid')gt-1||u.idexOf('Adr')gt-1,//adroid终端iPhoe:u.idexOf('iPhoe')gt-1,//是否为iPhoe或者QQHD浏览器iPad:u.idexOf('iPad')gt-1,//是否iPadweA:u.idexOf('Safari')==-1,//是否we应该程序,没有头部与底部weixi:u.idexOf('MicroMeeger')gt-1,//是否微信(2015-01-22新增)qq:u.match(/\\QQ/i)==quotqqquot//是否QQ}}(),laguage:(avigator.rowerLaguage||avigator.laguage).toLowerCae()}不同的浏览器设备显示不同内容//判断是否adroid浏览器if(rower.verio.adroidamam!rower.verio.weixi){alert(这是adroid浏览器)}//判断是否io浏览器if(rower.verio.ioamam!rower.verio.weixi){alert(这是IOS浏览器)}//判断是否微信浏览器if(rower.verio.weixi){alert(这是微信浏览器)}if(!rower.verio.adroidamam!rower.verio.ioamam!rower.verio.weixi){alert(非adriod和io以及微信浏览器)}

如何给网页css样式起个好名字?

加载中...
工作中为了页面方便维护,以及利于百度抓取,都会给c样式规范化命名,今天就来讲讲如何给网页c样式起个好名字?页头:header如:#header{属性:属性值}或.header{属性:属性值},也许你需要了解cla与id区别及用法登录条:logiBar标志:logo侧栏:ideBar广告:aer导航:av子导航:uNav菜单:meu子菜单:uMeu搜索:earch滚动:croll页面主体:mai内容:cotet标签页:ta文章列表:lit提示信息:mg小技巧:ti栏目标题:title加入:joiu指南:guild服务:ervice热点:hot新闻:ew下载:dowload注册:regiter状态:tatu按钮:t投票:vote合作伙伴:arter友情链接:friedLik页脚:footer版权:coyRight常用配合标签div、h1、h2、h3、h4、a、em、、trog、fot、u1.CSS的ID的命名也许你需要了解cla与Id区别外套:wra主导航:maiNav子导航:uav页脚:footer整个页面:cotet页眉:header版权:coyRight商标:lael标题:title主导航:maiNav(gloalNav)顶导航:toav边导航:idear左导航:leftideBar右导航:rightideBar旗志:logo标语:aer菜单内容1:meu1Cotet菜单容量:meuCotaier子菜单:umeu边导航图标:idearIco注释:ote面包屑:readCrum(即页面所处位置导航提示)容器:cotaier内容:cotet搜索:earch登陆:logi功能区:ho(如购物车,收银台)当前:curretDIV+CSS命名小结:无论是使用“.”(小写句号)选择符号开头命名,还是使用“#”(井号)选择符号开头命名都无所谓,但我们最好遵循,主要的、重要的、特殊的、最外层的盒子用“#”(井号)选择符号开头命名,其它都用“.”(小写句号)选择符号开头命名,同时考虑命名的CSS选择器在HTML中重复使用调用。通常我们最常用主要命名有:wra(外套、最外层)、header(页眉、头部)、av(导航条)、meu(菜单)、title(栏目标题、一般配合h1h2h3h4标签使用)、cotet(内容区)、footer(页脚、底部)、logo(标志、可以配合h1标签使用)、aer(广告条,一般在顶部)、coyRight(版权)。其它可根据自己需要选择性使用。DIVCSS5建议:主要的、重要的、最外层的盒子用“#”(井号)选择符号开头命名,其它都用“.”(小写句号)选择符号开头命名。2.CSS样式文件命名如下主要的mater.c布局,版面layout.c专栏colum.c文字fot.c打印样式rit.c主题theme.c也许你需要了解一下c引用到html方法

WEB前端优化(前端攻城狮需要了解的页面访问速度优化方案)

加载中...
页面访问速度是靠哪些因素决定的呢?答案包括三个:数据库,服务器,前端,呐另外两个和我们没关系就不说了,主要说一下前端方面需要注意哪些问题才能最好的优化访问速度。前端优化也是包括三个方面,HTML优化,CSS优化和JS优化(看起来像废话哈~)。优化的原则一个是要尽可能减少HTTP请求数量,另一个是要尽可能减少每次请求的数据大小。好啦不说废话了,下面直接说方法:1)CSSSrite技术听起来很高大上的一个技术,其实就是简单的拼图而已哒。CSSSrite就是将小背景图拼接在一张图片上,然后用背景定位属性(也就是ackgroud-oitio)来调用需要的背景图,这种方法的原理就是当你使用一整张大背景时,可以减少很多无谓的htt请求的时间,另外一张大图的图片大小要比很多张小图的大小总和要小,因为每一张图片都会自带一些图片文件信息,这些文件信息会占用一部分大小。说到这里也要提醒一下,如果不需要这些文件信息,也可以在保存时把相关的勾选去掉,那么图片大小也会变小。2)将CSS放在页面顶部,并且使用ltlikhref=quotxx.cquotgt,而不要使用@imorturl(xx.c)的方式来链接外部样式,因为ltlikgt可以与html同时解析,而@imort则会放在最后解析。3)避免使用CSS表达式,在属性里最好写确定的值,如果属性需要随某些条件改变时,最好在JS中去表现4)避免空的rc和href值当lik标记的href属性或crit标记的rc属性为空时,浏览器渲染时会把当前页面的url作为他们的属性值,也就是说会把页面内容重新加载进来作为他们的值。5)巧用浏览器缓存,尽量把CSS放在html外部,供多个页面调用,但是首页尽量不用外部CSS样式。6)不要在HTML中缩放图像,需要展示多大的图片,就将图片切成多大,不要让代码自己去计算。7)对javacrit和c文件进行压缩也许在编写代码时我们为了容易辨认,会经常使用空格,换行,注释等等,但这些在运行时会造成加载时间的无谓浪费,所以在上传之前,要另存一份,将其中所有不必要的内容删除,除了上面提到的,还包括语句最后的分号等等。当然这么繁杂的事情不需要你亲自动手,可以使用类似YUIComreor工具或者YahooUILiary。又一篇呕心之作完成了,随着对前端知识的逐渐了解,后续还会陆续发一些类似这样的自己总结的经验,结尾同样是那句话,求赞么么哒~

Web前端工程师的强者之路

加载中...
一入we前端深似海,从此休班成路人。从业这么多年来,换过不少工作,做过室内设计、平面设计、电商设计最后选择做we前端开发,我觉得自己跌入了无底深渊,自从做了这个行业之后,正常工作完还有回家不断的学习,从事we前端之后自学就没有间断过,养成了学习习惯之后,即使陪老婆逛会街都觉得自己在虚度光阴,晚上多看一会连续剧都觉得有些罪恶感,大家是不是觉得我病了,还病的不轻那,虽然我说的有些夸张,但是你是一名努力的we前端工程师,就应该和我有共鸣吧。We前端工程师和其他职业不同,比如平面设计,只要学会了Photoho及一些矢量工具,其他工具不需要学习太多,只要认认真真的提高自己的审美,不断丰富自己的知识,作品一般就不会差。室内设计也是一样,只要会了3dmax和cad,多去工地及建材市场了解一些工艺及材料就搞定了,也不是很累。We前端工程师为什么这么累?那么我就开始列举一下,Photoho这款软件必须会吧,哪怕你不会做效果图,简单的切图应该会吧,we前端既然是写代码的,起码要学习一块编辑器吧Dreamweaver的基本操作要学会,那么紧接着HTML和c就必须学了,想要让网页交互性和趣味性更加强一些,作为we前端工程师Javacrit这个就必须会,为了更好的用户体验Ajax这就必须会用因此PHP语法就必须了解一些,不然你怎么传递数据。想要工作这些东西花3-4个月的时间肯定能学会了,参加工作室没什么问题了,你是不是以为这样就完了那,完全错误。随着互联网的普及,越来越多的互联网产品的兴起,技术不断的更新,只具备以上这些技术根本是不行的,只能算是we前端菜鸟,不要提自己是工程师,会被嘲笑的。想要成为强者,你要不断的逼着自己学习,HTML5+c3的到来,we前端进行了一次洗牌,如果你不学习这个技术,你就会在这波激流中被淹没,随着2016年1月12日起IE浏览器将不再支持老版更新后,HTML5网站将大范围的在互联网进行覆盖,这个市场是巨大的,we前端工程师必须要开始学习这个了,通过几个月的加班总算学完了,总算松一口气,想要休班了,项目经理来到你的办工作说,客户都知道什么是响应式网站了,看来这个响应式网站我们是不做不行了。随着智能手机的大范围普及,平板电脑等移动设备的增多,响应式网站必定会成为未来的主流,这也是we前端工程师的工作,如果这个不学习,你的遭遇同上。又要加班...We前端工程师之所以这么拼,不断的学习,就是因为互联网是如今重要的传播媒介,通过新技术做出来的东西,很多人会自动为你传播,成为你的自来水,所以we前端技术是一个永远在前进的行业,如果你是一个不敢于创新的童鞋,那么这个行业几年间可能就会将你淘汰。我们学这么多不是为了给自己负担,个人认为只是为了一种职业的责任感,说的接地气一些就是为了能挣更多的钱,这个行业竞争非常的激烈,依然是三七法则,精英站三成却能拿到项目分红的七成,为了能够拿到更多,必须让自己成为精英,让自己变的更强。想要变的更强,下面是我的几点建议,希望能够帮助到各位。一、公司有大小,新手如何做选择?这里我们应该使用马克思的辩证唯物法,来看待这个问题。1.进入大公司。他们体系成熟,做事有套路,在这种环境下让你熏陶的是一种大公司的经营模式,可能你不太喜欢这种大公司环境,没关系,学上半年或一年,把这种理念烙印在你的思绪中,无论你后期自己创业还是去别的公司,这种思想都会成为你做事的规范,让你有大公司的范。2.进入小公司。有句老话叫不能输在起跑线上,但是我觉得起跑可能对于百米竞赛很重要,但是对于慢长的职业生涯来说不一定。先就业后择业对于多数普通的求职新人来讲是不错甚至是唯一的选择。在什么公司都能学到东西,关键看自己对自己职业的规划以及自己的努力程度。努力学,好好干,少讲条件,多做贡献。也许小公司资源不够,但是好在可以给你足够的空间发展,给你足够犯错误的耐心和承担。同时你还会结识一帮志同道合的兄弟,这在以后的职业生涯中,你都不知道重要到什么程度。在IT领域屌丝逆袭太正常了,那么多的大佬的起点比我们这些屌丝还惨,但是有梦想就有希望,万一成功了呢。二、丰富阅历,涉猎开阔你是一名we前端工程师,如果你单纯的只停留在写代码上,可能你就只是一个被禁锢的井底之蛙,我觉得你可以增加增加的爱好,可以多去看一些优秀的网页设计,目的是为了培养你的审美,因为网页设计师经常和we前端工程师掐架,因为很多网页设计师的作品很多细节部分,比如一像素的间距或者非常浅的颜色变化,we前端工程师看不到美,会将这些元素都给省略掉,想要和网页设计师处的更加和谐,建议we前端工程师多去看看好的设计作品,提高一下审美。三、善于交流,乐于分享如果你是一个好学的人,但是心胸狭隘,就怕被人把你辛苦研究的成果盗走,如果你善于分享,可能别人早就开发过了,你的代码中存在的ug可能很难找出,被别人一语点破,岂不是为你省去了很多时间,只要乐于分享的工程师,他的圈子将会越来越广,功底越来越深,所以提醒各位,要广交乐于分享的朋友们,让你的技术得到认可,并且从别人身上可以学习更多。在这里就先总结这三点吧,就不写太多了,所以希望我们年轻的朋友,脚踏实地,一步一个脚印的走,美好的明天一定会属于大家。我亲爱的学生们,当你们站在荣耀的舞台上时,我一定会在下面给你一如既往的掌声,一同分享实现梦想的幸福。

烧烤笔记

加载中...
1、我要发明一款吹风机,只要把头一伸,就吹出你要的发型。2、电动牙刷的设计还是不够科学,应该做到不用手。3、目前所谓互联网思维创业大部分都是:我开发一个软件,你下单我给你送家去。4、各大汽车厂商还在用自己的导航系统,还在开发各种low逼的娱乐系统,真够傻的,实际上只需要提供一根线即可:让手机界面同步车载屏幕就行了。5、停车场竟然还有人发卡或者自取卡收费,竟然没人开发手机二维码缴费。6、如何避免自己成为一个傻逼?对不熟悉的东西别说话。7、KTV都倒闭了吧?而我竟然从来没有请人去过。8、至今无人发明“用手机控制既能吸尘又能喷水擦地的工具”,真是人类的倒退。9、我国部分娱乐明星根本就不亲民,却偏偏要装出一副很亲切的样子,具体表现就是:“爱你们”、“陪我一路走过”、“幸好有你们”、“你们是我的坚强后盾”、“家人”……10、什么是low逼?过了四十岁还在网上跟陌生姑娘打情骂俏丝毫没想到屏幕前的自己早已成猪。11、淘宝屏蔽微信,微信打不开淘宝链接,微博屏蔽公众号…这都是倒退,都不配成为互联网的领先者。12、过去的地下摇滚拼命控诉社会,现在的流行歌手拼命狂唱爱情,除了那点可怜巴巴的爱来爱去就没别的了么?13、在“赞”的旁边,应该再加一个“艹”的按钮,这样就可以统计有多少人觉得博主是傻逼了。14、每次看到朋友们自称吃货,都认为这是自我侵犯人权,我觉得这是个贬义词,并且不存在贬义词褒用的情况。15、最喜欢的眼睛是高智商犯罪分子的眼睛,她们总是对一切保持警惕。16、每次看那些卖情趣用品的文案都有一种老军医的尴尬,她们为什么不直接大方的说:科技优化性生活。17、很多小女孩在商场莫名其妙的大哭,可能源于父母给她打扮落伍,希望他们好好考虑一下孩子的感受。18、批评年轻人在地铁里玩手机不看书不看报的人,大概不知道手机能看电子书能看新闻能玩游戏能减压。19、买东西是缓解抑郁的最有效方式,账单是重返抑郁的快捷方式。20、喜欢那些骗了我还跟我继续交往的人,这让我觉得还有希望拿回被骗的一切。21、在朋友圈里各种虚伪奉承吹捧的人就不要追求什么演出自由埋怨什么行业黑暗了。22、很多美剧看起来真实,是因为它有很多生活细节。而我国电视剧太假的部分原因是基本上吃饭都是吃米饭,太缺乏做饭的过程。23、为什么常有人说你幼稚说你不成熟?因为有些东西已经失去太久,而你却没意识到。

脱单必备!男人这样发朋友圈,妹子才会心动

加载中...
首先,我有一个问题,你们发朋友圈都是为了什么?我不相信你们是为了感慨生活什么的。大部分时候,我们发的朋友圈都是为了吸引妹子,但是我就要说了,其实现在很多人发出来的朋友圈是有问题的。什么问题?不会玩的人发的朋友圈基本都是low照漫天飞,会玩一点的基本也都是发的炫耀图,美其名曰“硬性价值展示”。我在这要告诉大家一些事情。纯粹的价值展示并不能获得吸引,反而会遭致厌烦,真正意义上能够被别人接受的价值展示都必须添加另外一个元素,那就是“健康的情感电路”。你可以把这个理解为是“情怀”,或者是“有温度”,总之就是不能单纯的只展示硬性价值。今天我们要给朋友圈展示一个新的定义。首先大家要明白我们发朋友圈的目的是什么,很纯粹,就是吸引妹子。那好了,吸引妹子无非就是想让女人做你的女友,但是你天天发一些玩闹和炫耀的照片,怎么可能让女人对你产生向往的感觉?她只会感觉这个男人是个玩家,然后对你没有安全感,从而疏远你。你必须要让女孩看到你的朋友圈之后产生一种心理:“如果这个家伙是我的男朋友该有多好。”只有产生了这种心理,你的朋友圈才可以称之为有效的朋友圈。当你这种展示越来越多之后,那么你就是大家微信里那个最适合做男友的男人,然后坐等被追。我们把这种朋友圈展示称为“男朋友的展示面”。那如何塑造这种朋友圈?我们来举例说明。大部分人喜欢发吃的图片,基本上就是下面这个样子:你们经常在朋友圈发到这种图片吧?我就问一句,有感觉么?除了炫耀你今天中午吃的还不错之外有什么意义?最后被人骂一句装逼然后快速划过。再来看看这张:硬性价值有了、身材有了、不错的生活环境、好看的花臂纹身,小露一截内裤,性暗示都做了。然后,这位男神在做饭。如果抛开做饭这件事,只是一个男人裸着上身,露个纹身,就算加个帅脸,充其量又是一个硬性价值的炫耀,女人只是觉得你长的不错,别的什么想法都没了。但是一旦加入做饭这个元素,画风就大变了,做饭是一种健康的情感电路展示。猜猜看,女人看到这样一个男人,她会想什么?她会不会也将自己想象(YY)在这张照片没有被拍到的某个角落,比如说......很多人喜欢在朋友圈发自拍或者单人照,我不是说这种照片是low的,只是无感。如果你长的帅,ok那还算是个硬性价值展示,如果长的不是很好看,那真的是在浪费所有人的时间。前段时间朋友圈非常流行一个狼人搂着一个小姑娘的图片,那张图片展示的是种保护,保护是健康的情感电路。就是下面这个:女人喜欢被人保护的感觉,也喜欢能够保护别人的男人。如果你的朋友圈能拍出类似的感觉,只要将保护这种元素渗透进去,即便是摆拍也不会妨碍激发他人的感觉,还是会觉得那很酷。比如说下面这个:笔挺的西装和墨镜,硬性高价值有了;伸手护着一个小女孩,健康的情感电路有了。“硬性价值”+“健康的情感电路”=男朋友的展示面。当然不一定非得拍成这个哥们这样,你只要把这个感觉搞出来就OK,呈现方式是很多的。我们也见过很多人喜欢拍狗的照片,据说养狗的人都是有爱心的,这个道理是没错,但是单纯地去拍狗,是拍不出这种感觉的。图片里有条狗怎么就能看出来你是有爱心的呢?最多就是狗好看而已,但是大部分狗不怎么好看。如果你想展示自己是爱护小动物有爱心的人,那你就必须和狗在一起,而且不可以是牵着,因为牵着狗,只会让人感觉你养了一条狗,最好是搞怪一点,能够体现出你和狗是平等的,你把它当作家人。比如说这哥们:穿着时尚,硬性价值有了,居然把狗随意地放在自己的包里,还是在一个自行车前篮里,健康的情感电路也有了。这张照片最亮的地方就是这个篮子里的包了,虽然里面装的是狗,但是大部分人会联想并产生一种很私密的亲近感,就像是儿时父亲在自行车大梁上载着自己,于是还有一种俏皮的轻松随意感随之产生。没错,一个穿着时尚的潜在“潮爹”这绝对是做男友的合适人选。一个好的朋友圈是让女人觉得你适合做男友,而不是一个只会炫耀的寂寞空壳。

HTML5+CSS3实现响应式设计,自动适配多种设备

加载中...
第一步:在网页代码的头部添加viewort标签viewort是网页默认的宽度和高度,上面这行代码的意思是:网页宽度默认等于屏幕宽度(width=device-width),原始缩放比例(iitial-cale=1)为1.0,即网页初始大小占屏幕面积的100%。所有浏览器都支持这个属性包括IE9(ie678不支持)第二步:不要使用绝对宽度width:auto/width:XX%第三步:字体大小和长宽边距属性字体大小和长宽边距属性不要用quotxquot,应该用相对大小的“remquothtml{fot-ize:100x}ody{fot-ize:0.14rem}div{addig:0.1remmargi-left:0.1rem}rem属性的更多解释请查看这篇文章前端程序员需要知道的7种新型的CSS长度单位第四步:流动布局quot流动布局quot的含义是,各个区块的位置都是浮动的,不是固定不变的.left{width:30%float:left}.right{width:70%float:right}这样写的好处是,如果宽度太小,放不下两个元素,后面的元素会自动滚动到前面元素的下方,不会在水平方向overflow(溢出),避免了水平滚动条的出现第五步:选择加载CSSquot自适应网页设计quot的核心,就是CSS3引入的MediaQuery模块。自动探测屏幕宽度,然后加载相应的CSS文件上面的代码意思是,如果屏幕宽度小于600像素(max-device-width:600x),就加载c600.c文件。如果屏幕宽度在600像素到980像素之间,则加载c600-980.c文件第六步:CSS的@media规则@mediacreead(max-device-width:400x){.left{float:oe}}当屏幕小于400时,left取消了浮动第七步:图片的自适应quot自适应网页设计quot还必须实现图片的自动缩放img{max-width:100%}widow平台缩放图片时,可能出现图像失真现象。这时,可以尝试使用IE的专有命令img{width:100%-m-iterolatio-mode:icuic}注:如有条件的话,最好还是根据不同大小的屏幕,加载不同分辨率的图片网页代码img{max-width:100%}video{max-width:100%height:auto}headerulli{float:leftlit-tyle:oelit-tyle-tye:oemargi-right:10x}headerelect{dilay:oe}@media(max-width:960x){headerul{dilay:oe}headerelect{dilay:ilie-lock}}*[Home](#)*[AAA](#)*[BBB](#)*[CCC](#)*[DDD](#)HomeAAABBBCCCDDD

前端程序员需要知道的7种新型的CSS长度单位

加载中...
众所周知CSS技术我们虽然很熟悉,在使用的过程却很容易被困住,这让我们在新问题出现的时候变得很不利。随着we继续不断地发展,对于新技术新解决方案的要求也会不断增长。因此,作为网页设计师和前端开发人员,我们别无选择,必须熟悉我们手上的工具,做到知己知彼,这样才能百战不殆。这就意味着有那么些个特别的货,虽然平常都不怎么会用上,但是一旦某个地方需要它们了,他们就真的是特么得合适不过来了呢。今儿,我就准备向大伙儿介绍一些你们之前可能很少见过CSS家伙们。他们每个都是度量的单位,类似ixel和em这样的,但是很有可能你之前从来就没听过这些家伙们!就让我们一起来交个朋友吧~rem我们首先介绍下和我们熟悉的很相似的货。em被定义为相对于当前对象内文本的字体大小。炒个栗子,如果你给ody小哥设置了fot-ize字体大小,那么ody小哥的任何子元素的1em就是等于ody设置的fot-ize。Tetody{fot-ize:14x}div{fot-ize:1.2em//calculatedat14x*1.2,or16.8x}你看,这里div这娃的字体大小是1.2em。解释来说,就是他从ody爹爹那里继承的字体大小(这里是14x)的1.2倍,结果就是16.8x。但是,如果你用em一层一层级联得定义嵌套元素的字体大小又会花生什么事情呢?在下面这一小段代码里我们应用了和上面一样一样的CSS,每一个div都从它上一级父元素继承了字体大小,并且逐渐得增加。TetTetTet虽然在某些地方这正是我们想要的,但是通常情况下我们还是希望就依赖单一的相对度量单位就好。这时候嘛,我们就可以使用rem了。‘r’是“root”的缩写,意思就是1rem等于根元素的字体大小;大部分情况下,根元素就是lthtmlgt元素了。html{fot-ize:14x}div{fot-ize:1.2rem}这样在上面的那三个嵌套的div娃们的字体大小都是1.2*14x=16.8x了。适用于网格布局Rem不仅仅只是在设置字体大小上很方便。再炒个栗子,你可以用基于html根元素字体大小的rem作为整个网格布局或者UI库的大小单位,然后在其他特定的地方用em单位。这样将会给你带来更多的字体大小和伸缩的可控性,.cotaier{width:70rem//70*14x=980x}概念上来说,这个方法的思想就是让你的界面根据你的内容进行缩放。但是,这样做并不是对所有的情况都有意义。vhadvw响应式We设计离不开百分比。但是,CSS百分比并不是所有的问题的最佳解决方案。CSS的宽度是相对于包含它的最近的父元素的宽度的。但是如果你就想用视口(viewoit)的宽度或者高度,而不是父元素的,那该肿么办?这就是vh和vw单位为我们提供的。1vh等于1/100的视口高度。栗子:浏览器高度900x,1vh=900x/100=9x。同理,如果视口宽度未750,1vw=750x/100=7.5x。可以想象到的,他们有很多很多的用途。比如,我们用很简单的方法只用一行CSS代码就实现同屏幕等高的框。.lide{height:100vh}假设你要来一个和屏幕同宽的标题,你只要设置这个标题的fot-ize的单位为vm,那标题的字体大小就会自动根据浏览器的宽度进行缩放,以达到字体和viewort大小同步的效果,有木有?!vmiadvmaxvh和vm依据于视口的高度和宽度,相对的,vmi和vmax则关于视口高度和宽度两者的最小或者最大值。比如,浏览器的宽度设置为1100x,高度设置为700x,1vmi=1x,1vmax=11x。如果宽度设置为800x,高度设置为1080x,1vmi就等于8x,1vmax则未10.8x。那么问题来了,我们应该在什么场景下使用这两个单位呢?假设有一个元素,你需要让它始终在屏幕上可见。只要对其高度和宽度使用vmi单位,并赋予其低于100的值就可以做到了。再来个栗子,可以这样定义一个至少有两个边触摸到屏幕的方形:.ox{height:100vmiwidth:100vmi}如果你要让这个方形框框始终铺满整个视口的可见区域(四边始终触摸到屏幕的四边).ox{height:100vmaxwidth:100vmax}结合使用这些单位可以为我们提供一个新颖有意思的方式来灵活地利用我们视口的大小。exadchex和ch单位,类似于em和rem,依赖于当前的字体和字体大小。但是,不同的是,这两货是基于字体的度量单位,依赖于设定的字体。ch单位通常被定义为数字0的宽度。你可以在EricMeyer的博客里找到关于它的一些有意思的讨论,例如将一个等宽字体的字母”N”的宽度设置为40ch,那么在另一种类型的字体里它却可以包含40个字母。这个单位的传统用途主要是盲文的排版,但是除此之外,肯定还有可以应用他的地方。ex定义为当前字体的小写x字母的高度或者1/2的1em。很多时候,它是字体的中间标志。x-heighttheheightofthelowercaex这些单位有很多用途,大部分用于版式的微调。比方说,u元素(上角文字标),可以通过oitio:relativeottom:1ex实现。类似的方法,你可以实现一个下角文字标。浏览器默认的方式是利用上标和下标特定垂直对齐规则,但是如果你想更细粒度更精确得控制,你可以像下面这样做:u{oitio:relativeottom:1ex}u{oitio:relativeottom:-1ex}结论持续关注不断发展壮大的CSS技术无疑是很重要的,这样你才能掌握你所持有的工具的全部技能。说不定将来你遇到的某个特殊的问题就需要使用这些复杂的单位来解决。

Git使用命令大合集

加载中...
之前一直用v,在同学的推荐下开始使用git,最常用的几个命令倒是熟悉,用的比较少的命令已经记不清了。要多多熟悉这些命令就要多练。接下来不废话开始正题。〉生成SSH$h-keyge-tra-Cquotemail@xxxquot将生成的SSHkey复制到文本框中即可(title默认为邮箱名)〉初始化当前目录的项目gitiit〉在该目录下新建一个文件,然后查看,将修改添加到暂存区echoquot#tetquotgtgtREADME.mdgitadd*//将工作区所有修改添加到暂存区gitadd.//将工作区所有修改添加到暂存区gitaddfileame//将指定文件添加到暂存区gittatu//列出变更文件〉将暂存区修改添加到本地仓库gitcommit-m'备注信息'〉创建仓库,并将上诉改动uh到远程gitremoteaddorigigit@githu.com:dreamwq/tet.gitgituh-uorigimater上面的地址填写你的githu地址。注:在这里遇到一个问题:每次uh都要输入用户名和密码,原因是htt方式uh,解决方法如下gitremotermorigi//移除gitremoteaddorigigit@githu.com:dreamwq/tet.git//添加此后就不用再输入用户名和密码了〉从远程cloe项目gitcloegit@githu.com:dreamwq/tet.git//这个链接填写你自己需要克隆的链接〉放弃暂存区修改gitcheckout--fileame//放弃暂存区修改(修改不在)gitrm--cachedfileame//放弃add(修改还在,但产生一条delete记录)gitreetHEADfileame//同上(没有delete记录)gittah//暂时放弃未提交的修改gittaho//恢复〉分支操作/*查看分支*/gitrach//所有本地分支gitrach-r//所有远程分支gitrach-a//所有远程分支和本地分支/*创建分支*/gitrachrachName//留在当前分支gitcheckout-rachName//创建并切换分支gitrach--et-utream-to=/rachName//建立本地分支与远程分支的追踪关系gitrach--trackrachName[remoterach]//新建一个分支,并与远程建立追踪关系gitcheckoutrachName//切到指定分支/*分支合并*/gitullorigirach//取回远程更新并与本地分支合并gitfetchorigirach//取回远程更新gitmergerach//合并指定分支到当前分支(产生提交记录)gitreaerach//合并指定分支到当前分支(不产生提交记录,比较适合有强迫症的)gitcherry-ickcommitId//将与commitId对应的提交合进当前分支好了,今天就到这里吧

Vue.js入门环境搭建

加载中...
vue这个新的工具,确实能够提高效率,在经历的一段时间的摧残之后,终于能够有一个系统的认识了,下面就今天的收获做一个总结,也是vue入门的精髓:1.要使用vue来开发前端框架,首先要有环境,这个环境要借助于ode,所以要先安装ode,借助于ode里面的m来安装需要的依赖等等。这里有一个小技巧:如果在cmd中直接使用m来安装的一些工具的话会比较慢,所以我们使用淘宝的m镜像:输入mitall-gcm–regitry=htt://regitry.m.taoao.org,即可安装m镜像,以后再用到m的地方直接用cm来代替就好了安装完m镜像后,开始安装全局vue-cli脚手架,之所以要用vue-cli,是应为这个工具能帮我们搭建好我们需要的模板框架,比较简单。方法:cmitall-gvue-cli回车,验证是否安装成功,在命令行中输入vue,出来vue的信息说明安装成功2.安装完脚手架以后开始,开始创建一个新项目:命令vueiitweackvue-xd(vue-xd这个是我创建的项目文件夹的名字)至此,一个新的项目文件夹就创建完成,这个项目文件是在使用了脚手架vue-cli的前提下创建的,所以使用了这个工具提供的默认版式,这就是使用脚手架搭建的项目文件的结构3.因为各个模板间都是相互依赖的,所以要安装依赖,在命令行输入cmitall,你会发现在已经创建的项目结构里面会多出一个ode_module的文件夹,里面就是刚才安装的所有依赖。4.准备工作做好以后,测试一下项目里面默认的a.vue模块能否跑起来,这是需要先安装一下服务器环境,在命令行中输入cmrudev回车即可8080就是默认的端口,在浏览器地址栏中输入localhot:8080会发现默认的模块打开了!

Sublime Text 3 快捷键汇总

SulimeText3非常实用,但是想要用好,一些快捷键不可或缺,所以转了这个快捷键汇总。用惯了vim,有些快捷键也懒得用了,尤其是在wi下面,还有图形界面,所以个人觉得最有用的还是搜索类,对于阅读和修改代码来说,非常实用。选择类Ctrl+D选中光标所占的文本,继续操作则会选中下一个相同的文本。Alt+F3选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑。举个栗子:快速选中并更改所有相同的变量名、函数名等。Ctrl+L选中整行,继续操作则继续选择下一行,效果和Shift+↓效果一样。Ctrl+Shift+L先选中多行,再按下快捷键,会在每行行尾插入光标,即可同时编辑这些行。Ctrl+Shift+M选择括号内的内容(继续选择父括号)。举个栗子:快速选中删除函数中的代码,重写函数体代码或重写括号内里的内容。Ctrl+M光标移动至括号内结束或开始的位置。Ctrl+Eter在下一行插入新行。举个栗子:即使光标不在行尾,也能快速向下插入一行。Ctrl+Shift+Eter在上一行插入新行。举个栗子:即使光标不在行首,也能快速向上插入一行。Ctrl+Shift+[选中代码,按下快捷键,折叠代码。Ctrl+Shift+]选中代码,按下快捷键,展开代码。Ctrl+K+0展开所有折叠代码。Ctrl+←向左单位性地移动光标,快速移动光标。Ctrl+→向右单位性地移动光标,快速移动光标。hift+↑向上选中多行。hift+↓向下选中多行。Shift+←向左选中文本。Shift+→向右选中文本。Ctrl+Shift+←向左单位性地选中文本。Ctrl+Shift+→向右单位性地选中文本。Ctrl+Shift+↑将光标所在行和上一行代码互换(将光标所在行插入到上一行之前)。Ctrl+Shift+↓将光标所在行和下一行代码互换(将光标所在行插入到下一行之后)。Ctrl+Alt+↑向上添加多行光标,可同时编辑多行。Ctrl+Alt+↓向下添加多行光标,可同时编辑多行。编辑类Ctrl+J合并选中的多行代码为一行。举个栗子:将多行格式的CSS属性合并为一行。Ctrl+Shift+D复制光标所在整行,插入到下一行。Ta向右缩进。Shift+Ta向左缩进。Ctrl+K+K从光标处开始删除代码至行尾。Ctrl+Shift+K删除整行。Ctrl+/注释单行。Ctrl+Shift+/注释多行。Ctrl+K+U转换大写。Ctrl+K+L转换小写。Ctrl+Z撤销。Ctrl+Y恢复撤销。Ctrl+U软撤销,感觉和Ctrl+Z一样。Ctrl+F2设置书签Ctrl+T左右字母互换。F6单词检测拼写搜索类Ctrl+F打开底部搜索框,查找关键字。Ctrl+hift+F在文件夹内查找,与普通编辑器不同的地方是ulime允许添加多个文件夹进行查找,略高端,未研究。Ctrl+P打开搜索框。举个栗子:1、输入当前项目中的文件名,快速搜索文件,2、输入@和关键字,查找文件中函数名,3、输入:和数字,跳转到文件中该行代码,4、输入#和关键字,查找变量名。Ctrl+G打开搜索框,自动带:,输入数字跳转到该行代码。举个栗子:在页面代码比较长的文件中快速定位。Ctrl+R打开搜索框,自动带@,输入关键字,查找文件中的函数名。举个栗子:在函数较多的页面快速查找某个函数。Ctrl+:打开搜索框,自动带#,输入关键字,查找文件中的变量名、属性名等。Ctrl+Shift+P打开命令框。场景栗子:打开命名框,输入关键字,调用ulimetext或插件的功能,例如使用ackage安装插件。Ec退出光标多行选择,退出搜索框,命令框等。显示类Ctrl+Ta按文件浏览过的顺序,切换当前窗口的标签页。Ctrl+PageDow向左切换当前窗口的标签页。Ctrl+PageU向右切换当前窗口的标签页。Alt+Shift+1窗口分屏,恢复默认1屏(非小键盘的数字)Alt+Shift+2左右分屏-2列Alt+Shift+3左右分屏-3列Alt+Shift+4左右分屏-4列Alt+Shift+5等分4屏Alt+Shift+8垂直分屏-2屏Alt+Shift+9垂直分屏-3屏Ctrl+K+B开启/关闭侧边栏。F11全屏模式Shift+F11免打扰模式