Javascript入门易,精通难,基本上是共识的一个观点。在这个篇幅里,主要对一些难点进行记录。

鸭子类型

Javascript属于动态类型语言的一种。对变量类型的宽容,给了很大的灵活性。由于无需类型检测,则无需考虑他是否被设计拥有该方法。

鸭子类型通俗说法:如果它走起路来像鸭子,叫起来也是鸭子,那么他就是鸭子

鸭子类型指导我们只关注对象的行为,而不关注对象本身。关注HAS-A 而不是 IS-A。

如下例子,不管什么动物,只要他会duckSinging,并且是方法,就可以加入。

  1. var duck = {
  2. duckSinging: function () {
  3. console.log("鸭子叫");
  4. }
  5. };
  6. var chicken = {
  7. duckSinging: function () {
  8. console.log("鸭子叫");
  9. }
  10. };
  11. var joinChoir = function(animal){
  12. if(animal && animal.duckSinging instanceof Function)
  13. {
  14. //可以加入
  15. }
  16. }

多态

同一个操作用于不同的对象上,可以产生不同的解释和不同的结果。举例:动作都会叫,那么叫就是操作。猫叫和狗叫的结果不一样,这就是多态。

Sound是同一个操作,所以使用prototype来在原型链上进行定义。将Cat生成为方法,是为了给他的原型链添加方法。如Dog就不属于多态。

  1. !(function () {
  2. var makeSound = function (animal) {
  3. animal.Sound();
  4. };
  5. var Cat = function(){};
  6. Cat.prototype.Sound = function () {
  7. console.log("喵");
  8. };
  9. var Dog = {}; //不属于多态
  10. Dog.Sound = function () {
  11. console.log("汪");
  12. }
  13. makeSound(Dog);
  14. })()

一种动物能否发出叫声,取决于他有没有Sound方法,而不是取决于他是那种对象。不存在任何类型耦合,这就是鸭子类型的典型。

原型模式

原型模式是通过克隆来创建对象的。我们只需要调用克隆方法,就可以完成功能。使用Object.Create方法,来实现克隆。

  1. !(function () {
  2. var Plance = function () {
  3. this.blood = 100
  4. };
  5. var plane = new Plance();
  6. plane.blood = 200;
  7. var clonePlane = Object.create(plane);
  8. console.log(clonePlane.blood);
  9. })()

可以重写拷贝方法,来进行自定义

  1. Object.create = Object.create || function(obj){ //Object.create || 意思是如果没有此方法
  2. var F = function () {};
  3. F.prototype = obj;
  4. return new F();
  5. };

继承

原型编程的基本规则

1.所有的数据都是对象

2.要得到一个对象,需要找到一个对象作为原型进行克隆。

3.对象会记住他的原型

4.如果对象无法响应某个请求,则会把这个请求委托给它自己的原型

javascript中绝大多数数据都是对象,除了undefined之外,都可以通过包装类的方式编程对象类型数据。

javascript中根对象是Object.prototype对象,他是一个空的对象。任何对象都是通过这个克隆而来的。

  1. var obj = function(){};
  2. var obj1 = {};
  3. console.log(Object.getPrototypeOf(obj) === Function.prototype);
  4. console.log(Object.getPrototypeOf(obj1) === Object.prototype);

Javascript中没有类的概念,那么new Person()这种,实际上是调用他的函数构造器,来进行初始化。函数既可以作为普通函数,也可以作为构造器。

  1. !(function () {
  2. var obj = function(na){
  3. this.name = na;
  4. };
  5. var obj1 = new obj();
  6. var obj2 = new obj('a');
  7. console.log(obj1.name); //undefined
  8. console.log(obj2.name); //a
  9. })()

请求可以在链条中往后传递,那么每个节点都必须知道它的下一个节点。Javascript给对象提供了一个名为_proto_的隐藏属性。

这个属性会默认指向它的构造器的原型对象。

  1. var obj = function(na){};
  2. console.log(obj.__proto__ === Function.prototype); //true

当对象无法响应某个请求的时候,他会顺着原型链把请求传递下去,直到有可以处理的请求对象为止。

以下是最常用的原型继承

首先obj2找,然后obj2对象构造器原型obj1原型,obj1原型找obj原型

  1. !(function () {
  2. var obj = function(){};
  3. obj.prototype = {name:'sven'};
  4. var obj1 = function () {};
  5. obj1.prototype = new obj();
  6. var obj2 = new obj1();
  7. console.log(obj2.name); //sven
  8. })()

对象构造器创建与对象克隆

对象构造器创建,只会创建该对象实体,不会创建该对象对应的原型。而克隆则是将原型也一并拷贝过去。

  1. !(function () {
  2. var obj1 = function(){
  3. this.name = 'sven'
  4. };
  5. var obj2 = obj1;
  6. var obj3 = Object.create(obj1);
  7. var obj4 = new obj1();
  8. console.log(typeof obj2.prototype); //object
  9. console.log(typeof obj3.prototype); //object
  10. console.log(typeof obj4.prototype); //undefined
  11. })()

this

this总是指向一个对象,对象是在运行时基于函数执行环境动态绑定的。

this指向大致分为四种

1.作为对象调用时,this指向该对象。

  1. var obj = {
  2. a:1,
  3. getA:function()
  4. {console.log(this.a);}
  5. };
  6. obj.getA();

2.作为普通函数调用时,this指向windows对象。

  1. window.a = 1;
  2. var getA = function(){
  3. return this.a;
  4. };
  5. console.log(getA());

3.作为构造器调用时,this指向他本身。

  1. !(function () {
  2. var myCla = function(){
  3. this.name = 'sven';
  4. };
  5. var obj = new myCla();
  6. console.log(obj.name); //sven
  7. })()

  但是,如果在方法中,进行闭包返回,那么结果就是最终返回的这个对象。

  1. !(function () {
  2. var myCla = function(){
  3. this.name = 'sven';
  4. return {
  5. name : "an"
  6. };
  7. };
  8. var obj = new myCla();
  9. console.log(obj.name); //an
  10. })()

4.作为call或apply调用时,可以动态的改变传入函数this.

  1. !(function () {
  2. var obj1 = {
  3. name:'sven',
  4. getName:function(){
  5. return this.name;
  6. }
  7. };
  8. var obj2 = { name : "an"};
  9. console.log(obj1.getName()); //sven
  10. console.log(obj1.getName.call(obj2)); //an
  11. })()

需要注意一点,就是对象变换。当你把对象引用到一个变量后,就会变成普通函数调用方法。例如:var get = obj1.getName; get(); //undefind

使用Apply也可以做到借用其他对象的方法

  1. !(function () {
  2. var A = function (name) {
  3. this.name = name;
  4. };
  5. var B = function(){
  6. A.apply(this,arguments);
  7. };
  8. B.prototype.getName=function(){
  9. return this.name;
  10. };
  11. var b = new B('save');
  12. console.log(b.getName());
  13. })()

闭包

闭包两大知识点就是变量的作用域以及变量的生命周期

变量的作用域

作用域是指变量的有效范围。

在函数中声明变量的时候,该变量前面没有var,则变为全局变量,任何地方都可以访问到。

使用var关键字在函数内声明,即是局部变量。只要函数内部才能访问。函数外面是访问不到的。

  1. var a = 1;
  2. var func = function(){
  3. var b =2;
  4. var func2 = function(){
  5. var c = 3;
  6. console.log(a);
  7. console.log(b);
  8. };
  9. console.log(c); //is not defined
  10. };

变量的生命周期

对于全局变量来说,声明周期是永久的,除非主动销毁这个全局变量。

对于函数内的局部变量来说,当退出函数时就会销毁。

使用闭包的话会一直存在在匿名函数的引用中,则不会销毁。因为,v返回了一个匿名函数的引用,可以访问到func()方法里面,局部变量a一直处在这个环境里。所以能被外界访问。

  1. !(function () {
  2. var func = function(){
  3. var a =1;
  4. return function(){
  5. a++;
  6. console.log(a);
  7. };
  8. };
  9. var v = func();
  10. var b = func();
  11. var c = v;
  12. v();
  13. b();
  14. c();
  15. })()

绑定事件

因为javascript事件都是异步触发的,当事件被触发的时候,循环就结束了,所以i会保持循环最后的数值。可以添加立即执行函数,来进行执行。

  1. var nodes = document.getElementsByTagName('div');
  2. for (var i = 0; i < nodes.length; i++) {
  3. (function (i) {
  4. nodes[i].onclick = function () {
  5. alert(i);
  6. }
  7. })(i)
  8. }

闭包和面向对象

使用对象以方法的形式包含过程,闭包是在过程中以环境的形式包含数据。两个都可以达到一样的目的。

  1. !(function () {
  2. var extent = function(){
  3. var value = 0;
  4. return {
  5. call:function(){
  6. value++;
  7. console.log(value);
  8. }
  9. };
  10. };
  11. var extent = extent();
  12. extent.call();extent.call();extent.call();
  13. //上为闭包写法,下为面向对象写法
  14. var extent2 = {
  15. value:0,
  16. call:function(){
  17. this.value++;
  18. console.log(this.value);
  19. }
  20. };
  21. extent2.call();extent2.call();extent2.call();
  22. })()

高级函数

currying(函数柯里化)

currying又称部分求值,当你传入函数的时候,不会立刻求值。会等到真正需要求值的时候,一次性求值。

  1. //封装计算框架,其中算法使用参数传递
  2. var currying = function (fn) {
  3. var args = [];
  4. return function () {
  5. if (arguments.length === 0) {
  6. return fn.apply(this, args);
  7. } else {
  8. [].push.apply(args, arguments);
  9. return arguments.callee;
  10. }
  11. };
  12. };
  13. //定义实际算法
  14. var cost = (function () {
  15. var money = 0;
  16. return function () {
  17. for (var i = 0; i < arguments.length; i++) {
  18. money += arguments[i];
  19. }
  20. return money;
  21. };
  22. })();
  23. var cost = currying(cost);
  24. cost(100);cost(100);cost(100);
  25. console.log(cost());

函数节流

某些场合下,函数被非常频繁的调用,会造成巨大的性能影响。比如说,瀑布流,窗口大小等。

使用函数节流,可以按照我们需要的时间忽略掉一些请求。使用setTimeout方法。

  1. //函数节流方法,第一个参数,执行函数。第二个参数,延迟时间
  2. var throttle = function (fn, interval) {
  3. var _self = fn, timer, firstTime; //定义函数引用,定时器,是否首次调用
  4. return function () {
  5. var args = arguments, _me = this;
  6. if (firstTime) { //第一次调用不延迟
  7. _self.apply(_me, args); //修正方法,传递参数
  8. return firstTime = false; //不进行延迟
  9. }
  10. if (timer) { //判断计时器是否存在
  11. return false; //存在代表尚在延迟时间内,忽略
  12. }
  13. timer = setTimeout(function () { //延迟执行一次
  14. clearTimeout(timer); //取消方法
  15. timer = null;
  16. _self.apply(_me, args);
  17. }, interval || 500);
  18. };
  19. };
  20. window.onresize = throttle(function(){
  21. console.log(1);
  22. },500);

分时函数

页面渲染DOM时候,为了避免一次性加载过多的节点,添加的分时函数操作。

  1. !(function () {
  2. //分时函数.参数1,创建节点数据。2.封装节点逻辑,3,每一批节点数量
  3. var timeChunk = function (ary, fn, count) {
  4. var obj, t;
  5. var len = ary.length;
  6. var start = function () {
  7. for (var i = 0; i < Math.min(count || 1, ary.length); i++) {
  8. var obj = ary.shift(); //删除一个数
  9. fn(obj);
  10. }
  11. };
  12. return function () {
  13. t = setInterval(function () {
  14. if (ary.length === 0) {
  15. return clearInterval(t);
  16. }
  17. start();
  18. }, 200);
  19. };
  20. };
  21. //实际调用方法
  22. var ary = [];
  23. for (var i = 1; i <= 1000; i++) {
  24. ary.push(i);
  25. }
  26. var renderFirendList = timeChunk(ary, function (n) {
  27. var div = document.createElement('div');
  28. div.innerHTML = n;
  29. document.body.appendChild(div);
  30. }, 2);
  31. renderFirendList();
  32. })()

Javascript知识点记录(二)的更多相关文章

  1. JavaScript学习记录二

    title: JavaScript学习记录二 toc: true date: 2018-09-13 10:14:53 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...

  2. Javascript知识点记录(三)设计模式

    Javascript设计模式记录,这个方面确实是没写过,工作中也没有用到js设计模式的地方. prototype与面向对象取舍 使用prototype原型继承和使用面向对象,都可以实现闭包的效果.那么 ...

  3. javascript知识点记录(1)

    javascript一些知识点记录 1.substring,slice,substr的用法 substring 和slice 都有startIndex 和 endIndex(不包括endInex),区 ...

  4. javascript知识点记录(2)

    1.js 异步加载和同步加载 异步加载模式也叫非阻塞模式,浏览器在下载js的同时,同时还会执行后续的页面处理, 在script标签内,用创建一个script元素,并插入到document中,这样就是异 ...

  5. 高性能javascript(记录二)

    js中有四种基本的数据存取位置.分别是:字面量.本地变量.数组元素.对象成员. 字面量:只代表自身,不存储在特定位置.js的字面量有:字符串.数字.布尔值.对象.数组.函数.正则表达式.以及特殊的nu ...

  6. 【千纸诗书】—— PHP/MySQL二手书网站后台开发之知识点记录

    前言:使用PHP和MySQL开发后台管理系统的过程中,发现有一些通用的[套路小Tip],这里集中记录一下.结合工作中ing的后台业务,我逐渐体会到:除了技术知识外.能使用户体验好的“使用流程设计”积累 ...

  7. JavaScript算法与数据结构知识点记录

    JavaScript算法与数据结构知识点记录 zhanweifu

  8. C#知识点记录

    用于记录C#知识要点. 参考:CLR via C#.C#并发编程.MSDN.百度 记录方式:读每本书,先看一遍,然后第二遍的时候,写笔记. CLR:公共语言运行时(Common Language Ru ...

  9. JavaScript基本概念(二)

    JavaScript 基本概念(二) 操作符和语句 目录 操作符 一元操作符 位操作符 布尔操作符 乘性操作符 其他操作符 语句部分 说起操作符,回忆下上一篇文章末尾说的话. 操作符 一元操作符 ++ ...

随机推荐

  1. sqlserver2012更改文件组

    1.查看文件组 sql语句 SELECT Data_located_on_filegroup = fg.groupname, Table_name = obj.name FROM sysfilegro ...

  2. [sql查询] 重复数据只取一条

    SELECT * FROM tab_init WHERE id IN ( --根据Data分类获取数据最小ID列表 select max(id) from tab_init group by a,b ...

  3. 集合2--毕向东java基础教程视频学习笔记

    Day14 08 LinkedList09 LinkedList练习10 ArrayList练习11 ArrayList练习2 12 HashSet13 HashSet存储自定义对象14 HashSe ...

  4. IP数据报首部解析

    IP数据报首部的格式,普通20字节. 4位版本号:当前4--IPv4. 4首部长度:首部长度 8位服务类型TOS: 3bits(优先权)+ 4bits(类型--最小延迟+最大吞吐量+最高可靠性+最小费 ...

  5. 深入解析SQL Server并行执行原理及实践(上)

    在成熟领先的企业级数据库系统中,并行查询可以说是一大利器,在某些场景下他可以显著的提升查询的相应时间,提升用户体验.如SQL Server, Oracle等, Mysql目前还未实现,而Postgre ...

  6. mac 安装mysql + 修改root用户密码 + 及报Access denied for user 'root'@'localhost' (using password:YES)解决办法

    1.下载MySQL 到mysql的官网http://dev.mysql.com/downloads/mysql/然后在页面中会看到“MySQL Community Server”下方有一个“downl ...

  7. 【小白的CFD之旅】05 补充基础

    黄师姐是一个很干脆果敢的人,从她的日常装扮就能显露出来.卡帕运动装,白色运动鞋,马尾辫,这是小白对黄师姐的第一印象.“明天早上九点钟来实验室,我给你安排这阵子的任务.”黄师姐对小白说.说话语气和老蓝一 ...

  8. [WPF系列]-数据邦定之DataTemplate 对 ItemsControl 进行样式和模板处理

    引言   即使 ItemsControl 不是 DataTemplate 所用于的唯一控件类型,将 ItemsControl 绑定到集合仍然很常见. 在 DataTemplate 中有哪些内容一节中, ...

  9. GCC 中零长数组与变长数组

    前两天看程序,发现在某个函数中有下面这段程序: int n; //define a variable n int array[n]; //define an array with length n 在 ...

  10. sql 入门经典(第五版) Ryan Stephens 学习笔记 后续——存储引擎

    一.引擎基础 1 查看系统支持的存储引擎 show engines; 2 查看表使用的存储引擎两种方法: a.show table status from database_name where na ...