重学前端-js篇

205 阅读4分钟

1.js中基本数据类型?

number string boolean null underfined object(Date、Array、 Function)symbol bigInt

具体情况:

Undefined: 类型表示未定义,它的类型只有一个值,就是 undefined。任何变量在赋值前是 
Undefined 类型、值为 undefined

Null: 表示的是:“定义了但是为空”

Boolean :类型有两个值, truefalse,它用于表示逻辑意义上的真和假,同样有关键字
truefalse 来表示两个值

String: 用于表示文本数据。String 有最大长度是 2^53 - 1,这在一般开发中都是够用的,
但是有趣的是,这个所谓最大长度,并不完全是你理解中的字符数。因为 String 的意义并非“字符串”
,而是字符串的 UTF16 编码,我们字符串的操作 charAt、charCodeAt、length 等方法针对的都是
UTF16 编码。所以,字符串的最大长度,实际上是受字符串的编码长度影响的。

Number:类型表示我们通常意义上的“数字”,这个数字大致对应数学中的有理数,
Number 类型有 18437736874454810627(即 2^64-2^53+3) 个值,
JavaScript 中的 Number 类型基本符合 
IEEE 754-2008 规定的双精度浮点数规则,
但是 JavaScript 为了表达几个额外的语言场景
(比如不让除以 0 出错,而引入了无穷大的概念),规定了几个例外情况:NaN,
占用了9007199254740990,这原本是符合 IEEE 规则的数字;
Infinity,无穷大;-Infinity,
负无穷大。另外,值得注意的是,JavaScript 中有 +0 和 -0,
在加法类运算中它们没有区别,
但是除法的场合则需要特别留意区分,“忘记检测除以 -0,而得到负无穷大”的情况经常会导致错误,
而区分 +0 和 -0 的方式,正是检测 1/x 是 Infinity 还是 -Infinity。根据双精度浮点数的定义,
Number 类型中有效的整数范围是 -0x1fffffffffffff0x1fffffffffffff,
所以 Number 无法精确表示此范围外的整数。

为什么在 JavaScript 中,0.1+0.2 不能 =0.3
所以实际上,这里错误的不是结论,而是比较的方法,正确的比较方法是使用 JavaScript 
提供的最小精度值:

  console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);
  
 检查等式左右两边差的绝对值是否小于最小精度,才是正确的比较浮点数的方法。这段代码结果就是 true 了。 
 
Symbol:是 ES6 中引入的新类型,它是一切非字符串的对象 key 的集合,在 ES6 规范中,
整个对象系统被用 Symbol 重塑

Object :对象的定义是“属性的集合”,属性分为数据属性和访问器属性,二者都是 key-value 结构,
key 可以是字符串或者 Symbol 类型

NumberStringBoolean,三个构造器是两用的,当跟 new 搭配时,它们产生对象,
当直接调用时,它们表示强制类型转换。

Symbol 函数比较特殊,直接用 new 调用它会抛出错误,但它仍然是 Symbol 对象的构造器。

2.隐式类型转换

巧妙运用 "+" 与 "-" 规则 转换类型

var nums = "you are good boy" + 11;     //转成字符串

var nums = "37" - 7; // 转成number 30 

var nums = "37" + 7; // 转成字符串 377



nums - 0  可以转成数字类型

nums + "" 可以转成字符类型

3. == 与 ===

** "==" **

1"123" == 123

20 == false

3null == undefined

4new Object() == new Object() 

5、[1,2] = [1,2]

6number == "string" ,"string"转成 number 进行比较 1 == "1.0" // true

7boolean == ? boolean 转成 number 进行比较 true==  1 false == 0 // true

8object == number | string 尝试对象转换为基本类型 new String('hi') =='hi' // true

** "===" 类型不同:返回false,类型相同 **

1null === null

2undefined === undefined

3NaN !== NaN

4new Object() !== new Object() 

4.类型检测判断?

** 1. typeof 判断函数对象和基本类型比较方便 数组,null就不行了 记录:**

typeof 100  "number"
 
 typeof true "boolean"
 
 typeof function "function"
 
 typeof (undefined)  "undefined" 
 
 typeof new Object ()  "object"

 typeof [1,2]   "object"
 
 typeof NaN "number"
 
 typeof null "object"
 

** 2.(对象) instanceof(函数/构造器) 基于原型链去判断数组,适合去判断自定义对象,也可以用来检测原生对象,在不同的iframe 和window 间检测时失效。**

obj instanceof Object 

obj 期望是一个对象,如果是基本类型 直接返回false Object 期望是一个函数对象活着函数构造器 ,如果不是抛出异常。

** 补写例子**

[1,2] instanceof Array === true;

** 3. Object.prototype.toString 适合内置对象和基元类型 ,遇到null 和undefined **

Object.prototype.toString.apply([]);  ===  "[object Array]";

Object.prototype.toString.applyfunction (){});  ===  "[object Function]";

Object.prototype.toString.applynull);  ===  "[object null]";

Object.prototype.toString.applyundefined);  ===  "[object undefined]";

ie 6/7/8Object.prototype.toString.applynull);  ===  "[object Object]";

** 4.constructor可以被改写 **


class Animal { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name); // call the super class constructor and pass in the name parameter
  }

  speak() {
    console.log(this.name + ' barks.');
  }
}

let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.

以上代码创造了 Animal 类,并且通过 extends 关键字让 Dog 继承了它,展示了最终调用子类的 speak 方法获取了父类的 name。比起早期的原型模拟方式,使用 extends 关键字自动设置了 constructor,并且会自动调用父类的构造函数,这是一种更少坑的设计。所以当我们使用类的思想来设计代码时,应该尽量使用 class 来声明类,而不是用旧语法,拿函数来模拟对象。

** 5.duck type ** 判断数组时》判断是否有相似的特征 join push length是不是数字

5、对象的创建 ?

** 1.对象的创建-字面量 **

var obj = {a:1,b:2};
 
 var obj1 = {a:1,b:2, c:{ d:1,e:2}};

** 2.new / 原型链的方式 **

	
   foo.prototype.z = 3;
   
   var obj = new foo();
   
   obj.y = 2;
   
   obj.x = 1;
   
   obj.x   // 1
   
   obj.y  // 2
   
   obj.z  // 3
   
   typeof obj.toString; // 'function'
   
   'z' in obj ; // true 在obj原型上找到z
   
   obj.hasOwnProperty('z'); // false 在当前对象obj上找不到z
   
   obj的 _proto_ 指向 foo.prototype ,foo.prototype的 _proto_ 指向      Object.prototype, Object.prototype 的 _proto_ 指向 null
   
   obj.z = 5;
   
   obj.hasOwnProperty('z') // true 
   
   foo.prototype.z // 3
   
   obj.z // 5
   
   obj.z = undefined;
   
   obj.z; // undefined 
   
   delect obj.z;
   
   obj.z // 3

** 3.object.create ** 创建一个空对象,对象的原型指向参数

var obj =  Object.create({x:1});

obj.x  // 1 

typeof obj.toString  // "function"

obj.hasOwnProperty('x');  //false

** obj -> {x:1} -> object.prototype -> null **

var obj = Object.create(null);

obj.toString // undefined

** obj -> null **

获取实例对象obj的原型对象,有三种方法。

obj.proto

obj.constructor.prototype

Object.getPrototypeOf(obj)

上面三种方法之中,前两种都不是很可靠。 __proto__属性只有浏览器才需要部署,其他环境可以不部署。而obj.constructor.prototype在手动改变原型对象时,可能会失效

创建对象 的4种方式:

var obj1 = Object.create({});

var obj2 = Object.create(Object.prototype);

var obj3 = new Object();

var obj4 = {};

6、 函数的声明 和 函数表达式

** 函数的声明:函数声明可以前置**

function add(){}

** 函数的表达式:**

var add = function (){
} 

(function(){
})();

return function(){ 
};

var add = function foo (a,b){  // 命名函数表达式
}

函数构造器 : 
var func = new Function ('a','b','console.log(a+b)); // 只能匿名
func(1,2);

7.this

** 1> 一般函数的this **

function f1(){
   return this;
}

f1()===window; // true ,global , object 
function f2(){
   "use strict";
   return this;
}

f2() === undefined;  // true

** 2> 作为对象方法的函数的this **

var o = {
prop:37,
f:function(){
return this.prop;
}
}

console.log(o.f()); // 37
var o = {prop:37};
function independent(){
return this.prop;
}
o.f = independent;
console.log(o.f()); // 37

** 3>对象原型链上的this**

var o = {
	f:function (){
    return this.a+this.b;
    }
};

var p = Object.create(o);
p.a = 1;
p.b = 2;

console.log(p.f()); // 5

** 4> get /set 中的this**

** 5> 构造器中的this**

function MyClass(){
this.a = 37;
}

var o = new MyClass();
console.log(o.a)  // 37

function C2(){
this.a = 37;
return {a:38};
}

o = new C2();
console.log(o.a); // 38

如果没有return返回值,this作为返回值,this对象的原型指向MyClass.prototype的空对象

** 6>call /apply 方法与this**

function add(c,d){
return this.a+this.b+c+d;
}

var o ={a:1,b:2};
add.call(o,6,7);  // 1+2+6+7
add.apply(o,[6,7]); // 1+2+6+7

function bar(){
console.log(Object.prototype.toString.call(this));
}

bar.call(7); // "[object Number]"

** 7>bind方法 与this (ie9+才支持)**

function f(){
return this.a;
}
var g =  f.bind({a:'test'});
console.log(g()); // test

var o = {a:37,f:f,g:g};
console.log(o.f(),o.g()); // 37 test

** 8>函数属性预留:**

** 9> 闭包 **

** 普通函数:**

function outer(){
	var localVal = 30;
	return localVal;
}
outer();

** 闭包:**

官方概念:闭包(词法闭包和函数闭包)是指一个函数或函数的引用,与一个引用环境绑定在一起,这个引用环境是一个存储该函数每个非局部变量(也叫自由变量)的表。

闭包,不同于一般的函数,它允许一个函数在立即词法作用域外调用时,仍可访问非本地变量。

优点:灵活方便 封装

缺点:空间浪费 内存泄露 性能消耗

function outer(){
	var localVal = 30;
	return function (){
    return localVal;
    };
}
var func = outer();
func();

闭包无处不在:举例:

!funciton (){
var localVal = 'good boy';
document.addEventListener('click',function(){
console.log(localVal);
});
}();

!function(){
var localVal = 'good boy';
var url = 'http://www.baidu.com/';
$ajax({
url:url,
success:function (){
console.log(localVal);
}
})
}();

** 闭包-常见错误之循环闭包 **

错误输出 4 4 4

document.body.innerHTML = "<div id=div1>aaa</div>
<div id=div2>bbb</div><div id=div3>ccc</div>";
for(var i = 0i < 4; i++){
document.getElementById('div'+i).
addEventListener('click',function(){
alert(i); // all are 4
});
}

如何能输出 1 2 3

document.body.innerHTML = "<div id=div1>aaa</div>
<div id=div2>bbb</div><div id=div3>ccc</div>";
for(var i = 0;i < 4 ;i++){
!function(i){
document.getElementById('div'+i).
addEventListener('click',function(){
alert(i); // 1 2 3 
}(i)
}

** 闭包-封装**

(function(){
  var _userID = 123;
  var _typeID = 'item';
  var export = {};
  
  function  conver(userID){
    return +userID;
  };
  
  export.getUserId=function(){
    return conver(_userID);
  };
  
  export.getTypeId=function(){
    return _typeID;
  };
  
  window.export=export;
}());

export.getUserId(); // 123
export.getTypeId(); // item
export._userID; // undefined
export._typeID; // undefined
export.conver; // undefined