Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript语言精粹阅读笔记 #10

Open
plh97 opened this issue Mar 18, 2018 · 0 comments
Open

JavaScript语言精粹阅读笔记 #10

plh97 opened this issue Mar 18, 2018 · 0 comments
Assignees
Labels
javaScript 关于js的一些事 博客 写一些前端技术记录 学习 如果不学习,那今天和昨天又有什么区别 看书 其实如果不看书的话,那么每天写的东西都和昨天一样,又有什么意思

Comments

@plh97
Copy link
Owner

plh97 commented Mar 18, 2018

This 的4种调用模式

  • 方法调用模式
  • 函数调用模式
  • 构造器调用模式
  • apply调用模式

方法调用模式

var myObject = {
  value: 0,
  increase: function(inc) {          // 此处不能用 => 来声明函数
    console.log(this);               // myObject本身
    this.value += typeof inc==='number'?inc:1;
  }
}
console.log(myObject.value);    // 0
myObject.increase();
console.log(myObject.value);    // 1
myObject.increase(33);
console.log(myObject.value);    // 34

这种通过this调用上下文对象的方法称为公共方法。this和上下文之间的绑定发生在它调用的时候。这种超级延迟的绑定使得this可以高度复用。

函数调用

当一个函数并非一个对象的属性的时候,那么他就被当作一个函数来调用,此时

'use strict';
var myObject = {
  value: 0,
  increment: function (inc){
    this.value+= typeof inc==="number"?inc:1;
  }
}
let add = (a,b) => a+b;
myObject.double = function (){
  var that = this;                           //   此处this指向函数本身
  var helper = function (){
    console.log('myObject.double', thar);    //  此处this在非严格模式☞全局,严格模式undefined
    that.value = add(that.value, that.value)
  }
  helper()
}
myObject.double();
console.log(myObject);

构造器调用模式

js语言是一门基于原型继承的语言,可以从其他对象继承属性,该语言是无类型的。这和当前编程语言的主流风格不符合,但是如果你在函数调用之前加上new的话,那么背地里将会创造一个连接到函数prototype成员的新对象,同时this会绑定到那个新对象上面。同时new前缀也会改变return语句的行为。

'use strict';
var Quo = function (str){
  this.status = str;
}
Quo.prototype.get_status = function (){
  return this.status;
}
var myQuo = new Quo('confused');
console.log(myQuo.get_status());   // confused

一个函数创造的目的就是为了结合new前缀来调用,那么我们称之为构造函数,但是JavaScript语言精粹并不推荐这种构造方法。

Apply调用模式

因为js是一门函数式面向对象编程语言,所以函数拥有方法。
apply方法让我们构建一个参数数组传递给调用函数,他也允许我们选择this的值,apply接受2个参数,第一个是要绑定this的值,第二个就是一个参数数组。

doms = document.querySelectorAll('div');
Array.prototype.slice.apply(doms).map(e=> e.id);  // doms是没有map的方法,经过apply后拥有了map方法。

今天之前一直有个疑问,为什么大佬们这么喜欢用try--catch

var try_it = function (args){
  try {
    console.log(whatever);    //  ReferenceError  sdsd is not defined
  } catch (e) {
    console.log(e.name+" ",e.message);
  }
}
try_it();
console.log(console);

并不会因为报错就不执行之后的代码,这体验还是不错的。

用js写一个fade的褪色动画

为什么要这样呢,之前一直是用css的来写这种收缩动画,直到后来,css越来越大(压缩后200kb),我抑郁了。yes i promise you can use let instead of var in js everywhere.

const fade = (dom) => {
  let level = 1;
  const step = () => {
    dom.style.backgroundColor = `rgb(255,255,${level})`;
    if (level < 255) {
      level += 11;
      setTimeout(step, 100);
    } else {
      level = 1;
      setTimeout(step, 100);
    }
  };
  step();
};
fade(document.body);

the differnet between function and arrow function in javascript

  • 你没看错,箭头函数不能用arguments获得参数
'use strict';
const a = function () {
  console.log(arguments);
};
const b = () => {
  console.log(arguments);
};
a(1, 2, 3);
b(1, 2, 3);

image

  • 箭头函数不能使用new
  • 箭头函数 this 指向函数本身,而普通函数严格模式指向undefined,非严格模式指向global

模块模式

var serial_maker = function(){
  // 返回一个用来产生唯一字符串的对象
  // 位移字符串由:前缀+序列号
  // 这包括一个设置前缀的方法,一个设置序列号的方法
  // 和一个产生位移字符串的gensym的方法
  var prefix = ' ';
  var seq = 0;
  return {
    set_prifex: function(p) {
      prefix = String(p);
    },
    set_seq: function (s){
      seq = s;
    },
    gensym: function(){
      var result = prefix+seq;
      seq += 1;
      return result;
    }
  }
}
var seqer = serial_maker();
seqer.set_prifex("Q");
seqer.set_seq(1111)
var unique = seqer.gensym();
console.log(unique);  // Q1000

联级(jQuery)

返回this而不是undefined,这样就可以实现jquery的链式调用。这和函数式编程又有所不同。另一个返回的是data数组。用es6的class手写一个jQuery,实现链式调用,

class TQuery {
  constructor(tArg) {
    this.version = 0.1;
    this.author = 'pengliheng';
    this.DOM = [...document.querySelectorAll(tArg)]
  }
  css (attr, value) {
    this.DOM.forEach(dom=> dom.style[attr] = value )
    return this;
  }
}
window.$ = tArg => new TQuery(tArg);

实现一个最简单版本的jQuery链式调用,同时改变背景颜色,字体颜色,字体大小。

$('body').css('background','pink').css('color','red').css('font-size','50px');

链式调用的效率,由于jQuery返回的是整个this.所以他是低效的。

//耗时:104ms
for (let i = 0; i < 10000; i++) {
  $('div');
}
//耗时:4.7ms
for (let i = 0; i < 10000; i++) {
  document.querySelector('div');
}

原型与继承 (事实上,用浏览器打印出来就能对原型链继承看得一清二楚!)

const myMammal = {
  name: 'Herb the Mammal',
  getName() {
    return this.name;
  },
  says() {
    return this.saying || '';
  },
};
const myCat = Object.create(myMammal);
myCat.name = 'mimi';
myCat.saying = 'meow';
myCat.purr = (n) => {
  let i;
  let s = '';
  for (i = 0; i < n; i += 1) {
    if (s) {
      s += '-';
    }
    s += 'r';
  }
  return s;
};
myCat.getName = () => `${this.says} ${this.name} ${this.says}`;
console.log(myCat, myMammal);

image

函数化,

到目前为止,我们所看到的继承模式一个弱点就是没有隐私,因为所有属性都会被继承,即可见

识别变量的类型

首先想到的自然是typeof,但他的que缺陷也是显而易见的
image
细想一下,为何不用constructor,,看图,没错,识别了[]和{},但是null和NaN,undefined报错,
image
改良一下的最终解决方案式,唯一美中不足的是,不能识别undefined,请再配合isNaN一起使用,用来识别number和NaN的区别
image
顺便一提,callapply的效果是一样的

Object.prototype.toString.call(123)      // [object Number]
Object.prototype.toString.apply(123)     // [object Number]

JavaScript - 精华

  • 函数是顶级对象:函数是有词法作用域的闭包。
  • 基于原型继承的动态对象
    • 对象是无类别的。我们可以通过普通的赋值给任何一个对象新增一个成员的属性,同时一个对象可以通过从原型继承成员属性。
  • 对象字面量和数组字面量:创建一个新对象和数组是非常方便的表示法。

JavaScript - 糟粕

  • ==!=, 为了不出bug,==应该禁止使用
'' == '0'            // false
0 == ''              // true
0 == '0'            // true
  • with, JavaScript提供了一个with语句,本意是快捷访问对象的属性,不过结果不可预料,应该禁止使用。
    下面的语句
with (object) {
    a == b;
}

with 在这门语言的出现,本身影响了JavaScript处理器的速度,他阻断了变量名词法作用域的绑定,他的本意是好的。

  • eval
    你可能会这样用
eval("myValue = myObject."+a+";")
  • continue 语句
    continue 语句跳到语句的顶部,我发现一段代码通过重构后移除了continue语句之后,性能得到了改善。
  • ++,--语句,这个也禁止使用,建议用i+=1替换。
  • 位运算符
&       and 按位与
|       or   按位或
^       xor  按位异或
~       not  按位非
>>      带符号的右位移
>>>     无符号的(用0补足)右位移
<<      左位移  

通常用于执行硬件处理,但JavaScript不处理硬件,所以位运算符很慢

  • funtion语句对比function表达式
    function 语句会发生被提升,
    而var生命函数则不会。就我个人而言是建议使用var生命一个函数的。
function test(){}
var test = function(){}

一个语句不能以function开头,因为官方表示假定单词以function开头被认为是一个funciton语句。可以用如下做法避免他。

(function (){
  var hidden_val;
  // 这个函数对环境有一些影响,但不会引入新的全局变量
})
  • void 应该避免使用。

全书完。

@plh97 plh97 changed the title This 的4种调用模式 JavaScript语言精粹阅读笔记 Mar 18, 2018
@plh97 plh97 self-assigned this Mar 18, 2018
@plh97 plh97 added 学习 如果不学习,那今天和昨天又有什么区别 博客 写一些前端技术记录 看书 其实如果不看书的话,那么每天写的东西都和昨天一样,又有什么意思 labels Mar 18, 2018
@plh97 plh97 added the javaScript 关于js的一些事 label Apr 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
javaScript 关于js的一些事 博客 写一些前端技术记录 学习 如果不学习,那今天和昨天又有什么区别 看书 其实如果不看书的话,那么每天写的东西都和昨天一样,又有什么意思
Projects
None yet
Development

No branches or pull requests

1 participant