了解这些js原理你将成为更好的developer

1.Number 类型

在js中只有一种数值类型,双精度的数字和小数位的数值的计算在js中是不准确的。

例如:0.1+0.2是无法和0.3相等的。但是整数型的1 + 2 === 3。

Number的数据类型继承自Number.prototype方法。可以在number类型上调用这些方法:

(123).toString();  //"123"
(1.23).toFixed(1); //"1.2"

parseInt() ,parseFloat(), Number(),这些全局方法可以转换为Number类型。

parseInt("1")       //1
parseInt("text")    //NaN
parseFloat("1.234") //1.234
Number("1")         //1
Number("1.234")     //1.234

无效的计算操作符或者无效的转换在将不会抛出异常,但是会得到NaN(Not a Number),isNaN()方法可以用于检测Not a Number

+号可以用于计算或者字符串拼接:

1 + 1      //2
"1" + "1"  //"11"
1 + "1"    //"11"

String类型:

可以用双引号或者单引号来表示字符串。

字符串类型的方法继承自String.prototype,例如substring(), indexOf(), concat()

"text".substring(1,3) //"ex"
"text".indexOf('x')   //2
"text".concat(" end") //"text end"

字符串类型具有不可变特性,例如concat()不会修改原来的字符串,而是会返回一个新的字符串。

Boolean类型

布尔类型有两个值: true 和 false.

以下等同于false:

false, null, undefined, ''(空字符串),0, NaN.

所有其他的值包括所有的对象都是等同于true,看如下例子:

let text = '';
if(text) {
  console.log("This is true");
} else {
  console.log("This is false");
}

Object类型:

Object类型是key value键值对的集合,key是个string,value的值可以是原始数据类型,对象或者函数。

创建对象常用的方式是使用对象字面量语法:

let obj = {
  message : "A message",
  doSomething : function() {}
}

我们可以再任何时候读取,新增,编辑,删除对象的属性。

let obj = {}; //创建对象
obj.message = "A message"; //新增属性
obj.message = "A new message"; //编辑属性
delete obj.message; //删除属性

如果你要让对象不可变可以使用Object.freeze()方法。

Object.keys() 返回对象自身的可枚举的所有属性。

原始类型VS对象

原始类型是不可变的,但是对象是可变的。

变量:

声明变量的方式有 var let const

let声明方式具有块作用域,通过const声明的变量不能再次声明。但是它的值是可变的。const冻结变量,Object.freeze()冻结对象。const声明具有块作用域。声明再函数之外的变量具有全局性。

 

Array类型:

数组元素可以通过下标来获取,索引会被转换为字符串,例如:

arr[1]===arr['1'];

还有一种就是称之为 array-like的类数组。

{
  '0': 'A',
  '1': 'B',
  '2': 'C'
}

如果你使用delete去删除数组元素的话这里有个坑。

let arr = ['A', 'B', 'C'];
delete arr[1];
console.log(arr); // ['A', empty, 'C']
console.log(arr.length); // 3

使用splice()方法可以避免这个问题,但是它的性能是比较慢的。

js是不会抛出索引超出范围的异常,如果索引不存在会返回undefined.

使用数组的方法我们可以模拟出栈和队列的概念.

let stack = [];
stack.push(1);           // [1]
stack.push(2);           // [1, 2]
let last = stack.pop();  // [1]
console.log(last);       // 2
let queue = [];
queue.push(1);           // [1]
queue.push(2);           // [1, 2]
let first = queue.shift();//[2]
console.log(first);      // 1

 

函数:

函数是对象,可以赋值给变量,储存在对象和数组中。作为参数传递给另外个函数或者作为返回值。

有三种方式定义一个函数:

1.函数声明

2.函数表达式

3.箭头函数

 

函数声明:

1.使用function作为第一个关键字

2.必须有个函数名name

3.调用函数可以位于函数的定义之前,函数声明会自动提升到作用域的顶部。

 

函数表达式:

1.function不是第一个关键字

2.函数名(name)是可选的,可以是一个匿名函数或者一个具名函数。

3.可以立即执行(IIFE)

 

箭头函数:

箭头函数是创建匿名函数的语法糖。

箭头函数没有属于他自己的this和arguments

 

通过function关键字声明的函数,可以通过不同的方法调用它

1.doSomething(param)

2.theObject.doSomething(param)

3.new DoSomething()

4.doSomething.apply(xxxxx)   doSomething.call(xxxx)

5. let doSomething = doSomething.bind(thisObject);

doSomething();

可以通过一个或者多个参数来调用函数,超出的参数将会被忽略,而少传递的参数将会赋值为undefined。

 

关于this:

this存在于函数的上下文。只有通过function关键字声明的函数才有this上下文。this的值取决于函数执行的环境。

 

关于return:

函数如果为声明return的情况下,默认会返回undefined。请注意如下示例

function getObject(){ 
  return 
  {
  }
}
getObject()

上面的示例中,函数将不会返回空对象。而是会返回undefined。(注意return和花括号再不同行上),为了避免这种情况需要如下改造这个函数:

function getObject(){ 
  return {
  }
}

 

动态类型:

js具备动态类型的特性,值有类型,变量则没有。类型可以再运行的时候进行更改。

function log(value){
  console.log(value);
}
log(1);
log("text");
log({message : "text"});

typeof操作符可以检测变量的类型。

let n = 1;
typeof(n);   //number
let s = "text";
typeof(s);   //string
let fn = function() {};
typeof(fn);  //function

 

单线程

javascript是单线程的,所以js无法再同一个时间同时运行两个函数。js运行时候包含事件队列,这个事件队列存储着需要处理的事件信息。他们不存在竞争关系,也不存在锁死情况。

 

异常处理

js有一套自己的异常处理机制,我们可以使用try/catch语法来捕获js中的异常。但是有时候js会静静的吞没错误。不会抛出任何的exception。以下示例,当修改被冻结(freezon)对象的时候,js将不会抛出错误。

let obj = Object.freeze({});
obj.message = "text";

再js中使用严格模式将会显示抛出这样静默错误。

 

原型链模式

Object.create(),构造器函数,class,将会通过原型链构建对象。

考虑下如下示例:

let service = {
 doSomething : function() {}
}
let specializedService = Object.create(service);
console.log(specializedService.__proto__ === service); //true

通过Object.create()构建一个新对象specializedService. service对象赋值为此对象的prototype,这就意味着doSomething方法存在于specializedService的原型链上。同时specializedService的__proto__属性指向service。

让我们通过class构建一个类似的对象。

class Service {
 doSomething(){}
}
class SpecializedService extends Service {
}
let specializedService = new SpecializedService();
console.log(specializedService.__proto__ === SpecializedService.prototype);

 

函数式模式

再js中函数作为一等公民,因此这使得函数式编程可以运用在js中。再函数式编程中有个高阶函数的概念,以函数作为参数或者返回的为函数,或者两者都有的再函数式编程中成为高阶函数。关于高阶函数的更多用法和概念可以参考社区里的博客文章。

 

posted @ 2018-08-04 19:41  我叫果果  阅读(124)  评论(0)    收藏  举报