跳过正文

Archives

第一次离拉花那么近

·43 字·1 分钟
工作之后,心血来潮,在京东下单了一台灿坤的意式家用半自动咖啡机。自己本身是一个很喜欢喝咖啡的人(一天离开咖啡就浑身不自在),但是经常喝速溶咖啡肯定对健康是不好的,喝星巴克又费钱,所以就入了一台咖啡机。现在已经爱上做意式咖啡这一过程了,同时对自己做的咖啡真心是喝不腻的。 苦于没有人教授,买了咖啡机两个月来,从来没有成功的到达拉花这个步骤。因为每一次奶泡总是打不好,奶泡总是过厚,奶泡和奶不能很好的融合,导致奶泡不够绵密,不够绵密的奶泡是无法进行拉花的,倒出来就是一坨坨的泡沫。趁着国庆这个假日,终于有时间能够好好研究下奶泡的打法,皇天不负有心人啊,下午终于成功了一次,打出来的奶泡是绵密的,很适合拉花(然而拉花失败了,没有把握好注入点)。 现在呢,总结下,打奶泡的过程吧,不要轻视这一过程,原本我也只是以为有个机器,只要打出奶泡就行了,什么事都是一键生成。这两个月随着一盒盒的牛奶钱付之东流,我才明白世界原来不是那么简单的(哭)。打个奶泡也是需要学习的,这真是充分说明了学习能力的重要性~看了那么多视频教程和原理讲解,总算是明白了,心疼前期的二逼打泡技术(还有我的牛奶和咖啡豆钱 T T)。 首先,硬件是必须元素: 意式半自动咖啡机。 咖啡机预热充足,放出蒸汽管中残留的水分,同时蒸汽管的水蒸气稳定 一个 350ml 的拉花缸(取决使用牛奶的量) 其次,原料也是很重要的: 必须使用脂肪含量大于 3.0%的纯牛奶(也叫全脂牛奶) 牛奶在 5 摄氏度下为益(当然不要低于 0 摄氏度) 牛奶多于拉花缸的 3 分之一 然后,打泡的手法: 蒸汽管起先保持在液面上(相切),并且倾斜于液面,蒸汽管的注入点为中心稍微靠人这一侧(不可贴缸壁),斜右上方 45 度靠杯缘处 打开蒸汽,蒸汽管发出嘶嘶的尖叫声(不要吓到,这是没问题的~),这个过程叫做发泡,此时要保证牛奶是在奶缸中小幅度旋转(不是的话,就是注入点错了),这个时候牛奶中的奶泡会越来越多,但是很多都浮在奶泡表面,得到自己想要的奶泡厚度后进入下一步骤(此时牛奶的温度大约 40 摄氏度)。需要注意的是,如果蒸汽管离奶平面太高,奶泡会变巨大;蒸汽管插入太深,就不会有奶泡,只是用花哨的技术加热了牛奶…… 等到奶泡到达你需要的量时,或者温度接近 40 摄氏度,将蒸汽管深入牛奶中,大概 1cm 的深度,此时进入打绵过程。这一过程,主要是让浮在表面的奶泡和底下的牛奶充分融合。注入点稍微往中间靠,依旧 45 度角倾斜,使牛奶旋转起来!此时正确的场景是这样的,牛奶不停的旋转(不跳跃),表面的奶泡在旋转下进入漩涡中间,逐渐消失,奶泡融入了牛奶中。这个过程是没有嘶嘶声的,等到牛奶温度到达 65 摄氏度左右,即可停止了。 最后,还没有结束的,打完的牛奶,呈现的是表面光滑,基本看不见泡泡。通过轻微晃动奶缸,让牛奶和奶泡更均匀,通过奶缸轻震桌面,让大泡泡消失。到这个时候,奶泡就真的完成了。 注意点是: 奶泡和奶是千万不能分离的,要融合 注入点一定要使得牛奶旋转!旋转!旋转!不许跳跃!发泡和打绵都要旋转!!全程旋转,奶泡基本成功~ 可以使用水,滴入洗洁精,观察注入点的流动方向(穷人福利)

腾讯试用期总结(2016年07月10日~2016年09月24日)

·26 字·1 分钟
工作职责: 作为 KM 平台中心开发组的员工,这段时间主要负责 KM 外网产品“乐享”的前端开发工作。其中涉及的工作为 PC 端的页面开发、移动端的 H5 开发、共有组件的开发和抽取等需求。主要表现为利用 jQuery、Seajs、LESS 等技术进行相关页面的数据处理,交互逻辑开发,共有组件的开发;利用 Laravel 等技术进行后台的业务逻辑的开发和维护。 工作成果(主要以开发模块做总结): 个人空间模块的前端和后台开发 公司首页、K 吧首页、论坛首页的页面改版 共有组件的开发和抽取 不足之处: 与设计师在设计稿的出稿时间上沟通不足,导致开发时间分配紊乱 对需求的一些边界条件考虑不够齐全,出现有时开发中出现重构的问题 改进计划: 分到需求后与设计师提前沟通好出稿时间,对设计工作量大的需求进行开发时间的隔离,避免设计工作量大的需求排在一起,优先级高的需求要优先处理 多与产品进行需求上的沟通,多从产品的角度去思考需求的潜在问题 每天适当空出时间进行新技术的学习

ES6实践(二)

·939 字·5 分钟
函数的扩展 # ES6 对函数进行了扩展,新的函数支持定义默认值、扩展运算符、写法更加简洁的箭头函数等。 函数参数的默认值(3 种形式) # 1.函数默认值 let fn = function (x = 1, y = 2) { return x + y; }; fn(); // 3 // 代替函数体内判断的写法 let fn = function (x, y) { x = x || 1; y = y || 2; return x + y; }; fn(); // 3 2.函数默认值——解构参数 可以通过解构变量来定义函数参数的默认值,减少参数的个数 let fn = function ({ x = 1, y = 2 }) { return x + y; }; fn(); // 3 3.函数默认值与解构赋值结合 注意:前面这两种方法都存在一个问题,如果只使用第二个参数,就必须给第一个参数传入undefined来指示第一个参数的默认值,通过解构赋值和函数默认值结合的形式可以避免这样的问题。 // 既可以不传入参数,也可以指定参数调用 let fn = function ({ x = 1, y = 2 } = {}) { return x + y; }; fn({ y: 2 }); // 3 实例:默认参数与解构赋值混合使用 let fn = function (x = 1, { y = 2, z = 3 } = {}) { return x + y + z; }; fn(5); // 10 rest 参数与拓展符 # ES6 也支持了函数 rest 形式的参数(使用者不需要考虑参数的个数),rest 参数必须跟在函数最后面,实例如下:

ES6实践(一)

·431 字·3 分钟
具体的 ES6 语法,可以参考阮一峰老师写的《ECMAScript 6 入门》。 该文章只整理一些实战中很有用的例子。 let&const # let 块级作用域变量声明 # let基本修复了以往var声明的弊端——变量全局污染,变量声明只在块级作用域中有效,不可重复声明,ES6 同时新增了新的块级作用域{},一些实用的例子如下: 1.代替原有的闭包创建的块级作用域 { // code } // 代替IIFE写法 (function () { // code })(); 2.解决 for 循环索引变化问题 // 循环结束i被垃圾回收 for (let i = 0; i < 6; i++) {} // 循环结束i的值为5 for (var i = 0; i < 6; i++) {} const 常量声明 # const解决了没有常量定义的问题,定义后的常量不能在修改,不可重复声明,同样的,常量声明只在块级作用域中有效,实用例子很简单:

阅读backbone源码——订阅-发布模式(pub/sub)

·668 字·4 分钟
订阅-发布模式 # Backbone.js最吸引人的基本上就是事件对订阅-发布模式(pub/sub)的使用了,一个典型的Backbone例子如下: // 新建一个model var Person = Backbone.Model.extend({ ... }); var person = new Person({}); // 绑定人名变更事件(订阅) person.on('callme', function () { alert('wayne'); }); // 修改人名,触发事件(发布) person.trigger('callme'); // 此时会弹出'wayne'的信息 // 解除事件绑定(取消订阅) person.off('callme'); person.trigger('callme'); // 什么都不执行 有了这个模式,我们就可以做到一些比较节省工作的事情,一个典型的应用场景——在线笔记: 用户在笔记的其中一个分类 backbone学习 点击添加一个新的笔记并保存 保存成功,笔记总数+1 使用jQuery的大致实现过程如下: $('#save-btn').click(function() { // 保存笔记 $.ajax(function() { success: function() { changeCount(); } }); };); 看着似乎没什么问题,但是如果需求改变了,比如变成这样: 用户在笔记的其中一个分类 backbone学习 点击添加一个新的笔记并保存 保存成功后,笔记总数+1、笔记编写界面刷新、本地笔记缓存同步、服务器缓存同步、自动分享到团队笔记中。。。 这个时候代码会变成这样: $('#save-btn').click(function() { // 保存笔记 $.ajax(function() { success: function() { dataView.changeCount(); noteView.refresh(); local.syncNote(); server.syncNote(); share.toMyTeam(); ... } }); };); 此时,各模块的代码严重耦合在了一起,写这段代码的人同时需要了解其他模块有什么函数,其他模块的编写者也不能随意更改自己的模块接口。

外卖小哥

·29 字·1 分钟
学校附近一家店有一个外卖小哥,年龄跟我差不多,二十出头,留着军队小兵的平头,皮肤是典型的东方黄,不偏不倚,大眼睛,浓眉毛,身高跟我也差不多,一米七几,说高不算,说矮也勉强,中等身材,约莫 120 斤,130 斤。 小哥平日里负责的是送外卖,主要服务对象也是学校里的学生,每天骑着一辆小电驴,电驴上驾着一泡沫箱装着的外卖,呼呼地穿梭于这几个校区之间。 可能是我名字比较特别,第二次点这家的外卖时,在宿舍楼下见到小哥,像往常一样报了宿舍名。小哥拿起写着我名字的那份,皱了下浓浓的眉毛。 “郑伟柏是吧?你的外卖。"。 “额……对”。 习惯于别人总是叫错我的名字了,我只是愣了下,并没有去更正小哥的话,我想叫错就错吧,也就拿下外卖而已。 接下来的日子里,说来也奇怪。小哥就这样记住了我错误的名字,隔了好长一段时间点他家的外卖,小哥每次送过来,电话接起,对面那头是直接喊起我的名字了。“郑伟柏,你的外卖,麻烦来楼下拿一下!",“郑伟柏,你外卖到了”,“郑伟柏,外卖在楼下!"…… 小哥不知咋地,叫我名字特勤快,每次隔了大老远,骑着小电驴,就叫我的名字,看了那么多次订单上的我的名字,却没有一次改正叫法,这让我觉得很是有趣。小哥每次都笑的很开心,远远的就看见他咧着大嘴,露出一口白牙,骑着小电驴跑上斜坡来,丝毫 没有因为这份日复一日,年复一年的枯燥工作心烦过。 临近毕业了。这几天下雨,又叫了他家的外卖,想想这应该是最后一次叫他家的外卖了吧!八点钟点的外卖,小哥 8 点 30 分来了电话,依旧是那熟悉的开头。下了楼,不见小哥的身影。过了两分钟,小哥穿着件旧蓝色的雨衣从斜坡上慢慢跑了上来,左手提着我的外卖,大老远的依旧是标志性的表情——咧嘴笑。 “哈哈,我电动车在斜坡下骑到一半没电了!郑伟柏,你的外卖啊!"。 “那你咋回去啊现在,这下大雨的,那电动车可以直接脚踏吧?"。 “哈哈,可以啊,我慢慢骑回去,就你一份而已,无所谓无所谓,送完就下班了都。得了得了哈,我下去牵车走了,再见再见”。 “嘿小哥。"。 “咋啦咋啦?"。 “我名字叫 ABC(这里代指三字姓名),不叫 ACB”。 “嘿,好好好,原来我老叫错了啊,ABC,不管不管,ACB 叫熟了都”。 小哥晃晃悠悠的跑下了斜坡,过会儿渐渐消失在雨中。 再见啦,有趣的外卖小哥。

PHP PDO参数绑定查询后,查看实际执行SQL的方法

·229 字·2 分钟
PDO 提供了一个PDOStatement::debugDumpParams — 打印一条 SQL 预处理命令的调试方法,但是打印出来的结果有点鸡肋,比如说: <?php try { $pdo = new PDO(); $sql = "SELECT * FROM `users` WHERE `username` = ? AND `email` = ?"; $stmt = $pdo->prepare($sql); $stmt->bindParam(1, $username, PDO::PARAM_STR); $stmt->bindParam(2, $email, PDO::PARAM_STR); $username = 'Saul Goodman'; $email = '********@qq.com'; $stmt->execute(); $stmt->debugDumpParams(); } catch (PDOException $e) { echo $e->getMessage(); } // 结果很感人: // SQL: [58] SELECT * FROM `users` WHERE `username` = ? AND `email` = ? // Params: 2 // Key: Position #0: // paramno=0 // name=[0] "" // is_param=1 // param_type=2 // Key: Position #1: // paramno=1 // name=[0] "" // is_param=1 // param_type=2 ?> 要是 SQL 语句一复杂这根本就阅读不了嘛!

chrome网页切换时,js定时器的问题

·52 字·1 分钟
原生 js 轮播组件的代码在这:https://github.com/wynn719/study-baidu-ife/tree/master/task0002/task0002_3 之前做的时候,会发现轮播在浏览器可见的情况下(没有缩小,没有切换标签),轮播是正常运行的;而当浏览器不可见的情况下(缩小, 切换标签),重新打开页面,轮播会出现几秒钟抽搐(真的很像)的现象,然后又恢复正常运行。 排除了动画逻辑,定时器泄露的问题,偶然情况下,发现 IE 下居然没问题! 看来崇拜的 chrome 也有抽筋的时候,**即 chrome 在浏览器不可见的情况下(缩小, 切换标签),会把定时器挂起(不会在后台运行),因此重新打开时,挂起的 n 个定时器突然运行,**所以 chrome 就抽风了! 说了这么多,解决方法很简单,只要监听这个事件 visibilitychange : // fix chrome下的bug,定时器切换选项卡时被挂起 document.addEventListener("visibilitychange", function () { if (document.visibilityState == "visible") { slide(); // 未挂起时执行轮播 } else if (document.visibilityState == "hidden") { clearInterval(timer); // 挂起时清除定时器 } }); 问题就解决了~ demo 展示在这:http://wynn719.github.io/study-baidu-ife/task0002/task0002_3/task0002_3.html (可恶,这个问题居然困惑了我好久,气煞我也,所以要记录下来……)

2015的读书小结

·6 字·1 分钟
从14年下半个学期开始,养成了读书的这个习惯,从一开始的厌倦到现在的欲罢不能,非常感谢昔日的自己能够坚持这个好习惯,并且让这个习惯成功的转型成了爱好。 以前从来不懂得读书的好处,“读了10本书后,你会以为身边不读书的人都很愚蠢;读了50本书后,你慢慢地发现自己才是最愚昧无知的人;你读的书越多,就越认识到自己的不足~”,这是在某个地方看到的,现在觉得真的很有道理。 既然是读书小结,那就不要太多废话了,直接贴图吧,感谢大神们做出了一个如此好用的豆瓣统计! 小结 # 今年读的书有点多啊,70本,读下来觉得似乎有点过了,接下来每年应该保持50本就差不多,不然吸收不了啊!再接再厉!

今天也要用心过生活

·166 字·1 分钟
最近读了一本书,松浦弥太郎的《今天也要用心过生活》,书里的道理总是很简单,印证那句老掉牙了的话:道理我都懂,但依然过不好这一生。突然想到,道理明明很简单,我缺乏的是主观能动性吧。生活本可以常驻新鲜,在看不到的地方保持自己的天真,curiosity,小孩子的天性,人长大后就没了,人也衰老的越来越快,心也就变硬了。 2015年快过去了,不管过的好不好,2016年终将来临。我想借由这本书的内容审视下2015年的自己,2015年所做得不好的地方要一一对自己指出,然后给2016年的自己好好指点一下迷津,让2016年的我活得更加有意义。 以下是书的内容和对自己的审视: Chapter 1 健康的早餐 # 每天的自我改造 2015:会尝试着学习一些小知识,小技能来丰富自己的生活,但持续性不好,一年下来不到100天 2016:一天中花时间学习小的爱好,争取做到持续时间大于150天 “早安”的功效 2015:经常会回避那些自己不喜欢接近的人(除去一些因为三观不合而不像认识的) 2016:多尝试主动与他们沟通,减少尴尬 让自己从容的一小时 2015:经常给自己独处的空间,这个做得挺好 2016:可以把这一小时从早起中抽出,继续保持 发现快乐,用心下功夫 2015:缺乏在小事中找快乐的能力 2016:如果感到做这件小事能够开心,那就尽管去做吧 发现全新自己的捷径 不认同,略过。 清洁的自信 2015:做得挺好的 2016:继续保持 起而行的行动家 2015:经常犹犹豫豫,但事后发现事情明明可以很快就做好决定,而且收效更好 2016:忌讳犹豫不决,从简单的事情开始做,小事在10分钟之内决定好,大事在1个小时到半天内决定好 自在的节奏 2015:对自己的生活节奏和工作节奏把握的不是很好,多半是因为情绪的波动导致自己节奏被打乱,没有注意合作伙伴的节奏,比如有时候容易打扰到别人,没有事先沟通好交流时间 2016:需要注意调整自己的节奏,同时也要注意合作伙伴的节奏,切勿心急 用心吃饭 虽然没有自己亲手去做饭,但一直很用心的吃饭,略过 优雅的握筷方式 不认同,略过 干净的姿态 2015:作为一个coder,虽然仪表是弄得比较整洁,但是姿态总是不够干净利落 2016:保持仪表整洁干净的同时,要多健身多锻炼,保持姿态的自然,落落大方,多注意不要弯腰驼背,坐下时不要老是头前倾 遇见“老师” 2015:遇到一些行为举止不雅的人,太容易意气用事了 2016:把那些你所厌恶的人和行为当作你自己的“老师”,有则改之,无则加勉,看不惯的东西,笑笑而过就好了 让笑容为生活保鲜 做得挺好的,继续保持 今天也要用心生活 2015:每个人都从内心里抗拒新事物的发生,抗拒面对新事物,有时候我会很喜欢去尝试新事物,但有的时候还是太畏畏缩缩,容易因为情绪失控而厌倦面对新事物 2016:年纪越大,越要有勇气挑战新事物,从小事调整开始,尝试着去学习身边每一个细微的事 Chapter 2 上乘的午餐 # 分享喜悦

CSS多行文字截断(适用移动端)

·89 字·1 分钟
废话不多说,直接讲一下常见的单行截断: <div class="single-line"> For a while I think we have got away with it, but then a flare goes up and we are caught suddenly in broad daylight. </div> .single-line { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 200px;/* 给一个宽度限制就可以出现...了 */ } 这个方法在各大浏览器都适用,然而当遇到需要多行截断时问题就来啦,除了粗暴的用后台来根据指定字数truncate掉,或者粗暴的写个jstruncate掉,其实还可以用纯css的方法来实现: <div class="multiple-lines"> For a while I think we have got away with it, but then a flare goes up and we are caught suddenly in broad daylight. </div> .multiple-lines { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; width: 200px; /* 一样要给一个宽度 */ } 唯一不足的是,如代码所见,对webkit内核的支持比较好,因此在移动端的兼容性会比较好(移动端大部分浏览器都是webkit内核)

js for循环中删除数组的某一项

·95 字·1 分钟
从后台返回的数据经常是以数组的形式传递过来的,开发中遇到的一个小问题,js在处理数组删除时很灵活,故记笔记。 for循环删除数组的某一项,一般的会马上这么写代码: for(var i = 0, len = array.length; i < len; i++){ if (array[i] === number) { array[i].splice(i, 1); } } 但是这样是不行的,因为数组的长度已经改变,这样会造成数组越界,这时可能会想到这样写: for(var i = 0; i < array.length; i++){ if (array[i] === number) { array[i].splice(i, 1); } } 同样也行不通,因为数组的索引变化难以把握 正确的做法: for(var i = array.length - 1; i >= 0; i--) { if(array[i] === number) { array.splice(i, 1); } } 这样可以保证数组 splice 后,循环还按正常的逻辑运行。 当然,如果想保证索引不改变的话,可以使用 ES5 的新操作符 for(var i = 0, len = array.length; i < len; i++){ if (array[i] === number) { delete array[i]; // 索引逻辑不受影响哦! // 需要浏览器支持的话,可以尝试把`array[i]`置为null // array[i] = null; } }

sticky footer

·87 字·1 分钟
开发中经常会碰到的一种情况是:由于页面的内容不够长,无法撑开页面,导致底部的模块下面留下一大块空白,实在不雅,sticky footer 技术解决了这个问题 1.页面结构: <div class="page-wrap"> <div class="header">header</div> <div class="content"> <button id="add">Add Content</button> </div> </div> <div class="site-footer">footer is!</div> 2.css:因为此处使用到了 after 伪元素,所以也就意味着 IE7 以下是无法使用该方法的 * { margin: 0; padding: 0; } html, body { height: 100%; /* 注意,这是必须的 */ } .header { height: 100px; background-color: #ffff80; } .page-wrap { min-height: 100%; margin-bottom: -150px; /* 必须与footer高度相等 */ } .page-wrap:after { content: ""; display: block; height: 150px; } .site-footer { height: 150px; } .site-footer { background-color: #0080ff; } 3.原理: margin-bottom 将 footer 向上拉动 :after用于当页面长度超过屏幕时占位把 footer 向下挤 footer 必须位于最外层,这也 DOM 结构有所不规范

记腾讯面试

·9 字·1 分钟
转眼间,我已经在腾讯实习了两个月了。 回想起今年4月,BG叫我一起去报腾讯的校招,我当时很犹豫,总觉得自己的能力还不足以去腾讯实习。“去看一看笔试考什么也好啊,就当做是练练胆,为以后做准备嘛。”,当时BG是这样跟我说的,然后我就抱着看笔试题的心态跑去笔试了(汗……) 4人的小分队跑去腾讯笔试,全部都通过了笔试,其实我笔试写得不怎么好,也不知道是为什么就过了……一面的面试官,也就是我现在的leader,面了有30分钟,全部都问的是前端的知识,可能跟我的简历有关吧(简历上除了前端相关的就没有别的了,还要说一句,简历真的是粗制滥造啊,跟旁边一群简历弄得漂漂亮亮的小伙伴们比起来真是相形见绌啊!=_=),面完后的第一感觉就是–结束了。当时还很庆幸有过来面试,leader给了我很多前端学习的建议。然而,过了好几天,居然被通知面试过了,当时没有很开心,反而是更担忧了…… 二面,4人小分队只剩下3个人,雪糕弟掉队了~二面之前,我翻了翻网上别人写的腾讯二面经历,妥妥的技术面,全方位知识各种考验。可是二面的面试官却出乎了我的意料,到了之后,没怎么问技术的问题,只是问了我对前端的认识,我就噼里啪啦的说了一堆。30分钟的面试,剩下的5分钟都是在问我能够实习多久的事,真的吓坏我了!我还是以为结束了,然而,过了好几天,又被通知三面。 三面只剩下2个人了,就是我和BG。HR面,聊人生,聊思想,聊性格,聊未来……是的,HR面就是在聊天,HR人很好,见我有点紧张,一进来就帮我拿书包和推椅子,是的,我更紧张了~HR在我临走之前还是给了我一些鼓励,让我很惊讶,当时就觉得腾讯的人真的好好,情商都好高。 剩下的日子,很多小伙伴都是在担忧中度过。对于我,其实挺无所谓的,毕竟面试给我带来了挺多的知识,或许是这种淡然的态度,给我迎来了这次实习的机会。 很凑巧,最后一轮面试,只有我通过了,每一轮走一个小伙伴,真的让我很不舒服,很希望能更他们一起实习。 转眼间在腾讯实习了两个月,又到了腾讯校招的时候了,小伙伴们也重新踏上了这条路,有时候会想,要是当时我没有去报名,那今天的我也不会有这么大改变,或许还是默默无为~真的是验了一句话——不逼自己一把,永远不知道自己有多厉害。 每年母上总会去帮四个孩子求签,而我每年都有四个字——戒骄戒躁,望自己能践行。

百度ife-javascript构造函数学习笔记

·286 字·2 分钟
constructor 是什么 # 当我们创建一个构造函数时,就会创建一个 constructor 的属性 function Foo() { this.name = "Jimmy"; } // 实例化对象 var foo = new Foo(); console.log(Foo.constructor); // Function() console.log(Foo.prototype.constructor === Foo); // true console.log(foo.constructor); // Foo() console.log(foo.constructor === Foo); // true 由于 Foo 本身是由 Function 创建的,所以 Foo 的 constructor 就自然而然的指向了 Function(),而 foo 是由 Foo()创建的,所以 foo 的 constructor 就指向了 Foo,即 constructor 默认指向创建自己的函数。 要注意的是,Foo.prototype.constructor 也指向 Foo,其实就是一个循环引用,Foo 的 prototype 属性指向 Foo 的原型,然后 Foo 的原型的 constructor 属性指向 Foo 即:Foo.prototype -> Foo 原型,Foo 原型的 constructor -> Foo

百度ife-javascript面向对象学习笔记

·916 字·5 分钟
javascript 不具有其他语言的类,继承等的特性,因此 javascript 的面向对象编程更多的是基于构造函数和原型的方式实现类的功能;基于原型链来实现类的继承;基于闭包的原理来实现私有化; 当然也有非原型链的继承,如 jquery 中使用的对象拓展(extend),通过对对象的 深度复制来实现。 javascript 面向对象编程 # javascript 本身不具有类的特征,那如何模拟类的特征呢? 一些好的尝试,但不够完美 # 在此之前,有工厂模式,有构造函数模式,但都存在着一些大的问题: 工厂模式的问题:无法识别对象是由谁创建的 构造函数的问题:在创建每个实例时,构造函数给每个实例的新建了方法,即使该方法本身是一模一样的,而面向对象的思想并不希望方法是一样的但是却要重复的创建,这本身浪费内存空间 原型模式 # 为了解决工厂模式和构造函数模式的问题,于是有了原型模式 把共享的变量和方法都放到原型上,然后让子类的原型与父类的原型建立关系,就实现了原型式继承 代码如下: function Person(){} // 定义要共享的方法 Person.prototype.name = 'Jimmy'; Person.prototype.sayName = function(){ console.log(this.name); } // 或者另一种写法 Person.prototype = { constructor: Person, // 不要忘记修正constructor指向 name : 'Jimmy', sayName = function() { console.log(this.name); } } 但是原型模式也存在着一些问题:

百度ife-javascript闭包学习笔记

·364 字·2 分钟
学习任务来自:百度ife前端技术学院 学习资料参考自: 闭包 深入理解javascript原型和闭包 在经过前面作用域和原型、原型链的学习,感觉遇到闭包也不怕啦… 准备被虐杀! 先补全一些作用域上的知识: 自由变量 # 在A作用域中使用的变量x,却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量。 例如: var x = 10; function fn(){ var b = 20; // x不在fn的作用域中声明,但却调用了 // 因此x叫做自由变量 console.log(b + x); } 一个经常容易犯错的例子: var x = 10; function fn() { console.log(x); } function show(f) { var x = 20; fn(); } show(); // 10 这个例子中,输出的不是20,而是10,因为在函数定义的时候就已经决定了函数的上下文执行环境,故,fn的作用域链上,只能找到window执行环境下的变量x

百度ife-javascript原型学习笔记

·430 字·3 分钟
学习任务来自:百度 ife 前端技术学院 学习资料参考自: JavaScript 探秘:强大的原型和原型链 理解 JavaScript 原型 深入理解 javascript 原型和闭包 个人注:主要是区分Prototype,prototype,__proto__,[[Prototype]],理解constructor Prototype:原型本尊 prototype:原型属性,指向Person,实例中不存在 __proto__:原型访问器,指向 创造该对象 的原型 [[Prototype]]:等同于__proto__ constructor:构造函数,指向函数本身(如 new Person),constructor.prototype也指向Prototype javascript 原型和原型链 # 对象中的proto属性(隐式原型,javascript 并不希望我们访问到该属性) # 每当创建一个对象,该对象就会有一个__proto__属性,该属性指向创建该对象的函数的原型

百度ife-javascript作用域学习笔记

·420 字·2 分钟
学习任务来自:百度ife前端技术学院 学习资料参考自: 28 May 09 Javascript作用域原理 JavaScript 开发进阶:理解 JavaScript 作用域和作用域链 javascript的作用域链 # javascript中的函数运行在她们被定义的作用域里,而不是它们被执行的作用域里 – 《javascript权威指南》 注意:在JS中,作用域的概念和其他语言差不多, 在每次调用一个函数的时候 ,就会进入一个函数内的作用域,当从函数返回以后,就返回调用前的作用域. javascript中作用域的实现方式与C/C++不同,不是使用“堆栈”的方式,而是使用列表,实现过程如下(ECMA262): javascript高级程序设计3中,指出函数的执行环境是保存在环境栈中的,执行完函数后,会把函数环境弹出栈 ……为何不一样的说法啊(高程中没有探讨到[[scope]]上) 作用域链(scope chain):保证对执行环境有权访问的所有变量和函数的有序访问。 任何执行上下文时刻(context)的作用域,都是由作用域链(scope chain)来实现的。 在一个函数被定义的时候,会将它定义时刻的scope chain链接到这个函数对象的[[scope]]属性。 在一个函数对象被调用的时候,会创建一个活动对象(object),然后对每一个函数的形参(arguments),都命名为该活动对象的命名属性,然后将这个活动对象做为此时的作用域链(scope chain)最前端,并将这个函数对象的[[scope]]加入到scope chain中。 解析这个例子: var func = function(lps, rps){ var name = 'laruence'; ........ } func(); 它的解析过程是这样的: