[TOC]

1.变量类型和计算

变量类型包括:值类型和引用类型

  值类型演示:  值不受影响<br />var a = 100 <br />var b=a<br /> a= 200 <br />console. log (b)   //100

引用类型演示:age相当于一个内存,最后被b重新赋值,那么a的值受影响
var a= {age:20}
var b= a
b. age = 21
console. log (a. age) //21


2.typeof 运算符详解

typeof 能清晰分出值类型,不能分出引用类型(除了function)
typeof undefined // undefined
typeof ‘abc’ // string
typeof 123 // number
typeof true // boolean
typeof console.log //function

typeof {} // object
typeof [] // object
typeof null // object

3.强制类型转换(变量计算)

3.1.字符串拼接

var a= 100+10 // 110 这是加法,不是字符串拼接
var b= 100+ ‘10’ // 10010 涉及到字符串拼接转换,因为100是一个值,’10’是一个字符串,类型不一样

3.2.==运算符 (慎用)

=== 不会进行强制类型转换,== 会进行强制类型转换

100 == ‘100’ // true == 会强制两边不同类型的进行转换;把100变成字符串
0 == ‘’ // true 把 0 和 ‘’ 都变成false就变成true了
null == undefined // true 把 null 和 undefined 都变成false就变成true了

何时使用 === 和 ==?
答: var obj = {}
if (obj.a == null) {
//要先定义obj才能使用if
//这里相当于obj.a === null || obj.a === undefined ,简写形式
//这是jquery源码中推荐的写法
}


3.3.if语句

var a = true
if (a) {
        //... if true 会怎么样
}

var b = 100 
if (b) {
        //....if 100 会怎么样
}

var c = '' 
if (c) {
        //....不会执行,因为 c 强制类型转换变成 false
}

if 里面是false的方式
0、NaN、’’、null、undefined、false

3.4.逻辑运算

console. log(10 && 0) (与) // 0 会把10强制类型转换是true还是false,true则0
console. log( ‘’ || ‘abc’) (或者) // ‘abc’ 会把’’ 强制类型转换成布尔类型,’’是 false
console. Log(!window.abc) (非)// true window.abc 没有值,则是 undefined,取非则true

//判断一个变量是 true 还是 false?
var a = 100
console. log(!!a)

3.5.JS的内置函数

//问题: JS中有哪些内置函数-数据封装类对象
object :对象
Array :数组
Boolean :布尔
Number :数字
String :字符串
Function :函数
Date :日期
RegExp :正则表达式
Error :错误

3.6. JS变量按照存储方式区分变量类型

JS变量按照存储方式区分为哪些类型,并描述其特点

//值类型
var a=10
var b=a
a=11
console. log(b)         // 10


//引用类型
var obj1 = {x:100}
var obj2 = obj1
obj1.x= 200
console.log(obj2.x)        // 200

3.7.如何理解JSON

问题:如何理解JSON
//JSON只不过是一个JS对象而已,也是数据格式。
JSON. stringify({a:10, b:20}
JOSN. parse( ‘{“a”:10,”b”: 20}’)

3.8.typeof symbol [ES6变量类型]

symbol 实际使用场景不多(作用:为了防止对象里面的key重复,而导致key被覆盖)

var s = Symbol()
typeof s     // "symbol"

var s1 = Symbol()
s === s1   //false ,每次由symbol生成的都是一个独立的值

var s2 = Symbol('bbbb')
s2     // Symbol(bbbb)  能区分字符串

var s88 = Symbol('bbbb')
s88     // Symbol(bbbb)
s2 ===  s88
//false ,每次由symbol生成的都是一个独立的值,都是不相等的

var sName = Symbol(‘name’)
var obj1 = {sName: ‘zhangsan’}

var sName1 = Symbol(‘name’)
obj1. sName1 = ‘zhangsan’

输出:obj1
//{sName: “zhangsan”, name: “lisi”,’sName1: “zhangsan”} Symbol的结果不会被覆盖

4.原型和原型链

4.1.构造函数

基本上看到函数名以大写开头的都是构造函数(Foo),如果后期你来维护代码你也要使用大写开头,不然不受待见

function Foo(name, age) {
    this. name name
    this. age = age
    this. class = 'class-1'
    // return this //默认有这一行
}

var f = new Foo('zhangsan', 20)
    // var f1 = new Foo('lisi', 22) //创建多个对象

4.2.构造函数一扩展

Object的构造函数
var a={} 其实是 var a = new Object() 的对象语法糖

Array的构造函数
var a =[] 其实是 var a = new Array() 的数组语法糖

Function的构造函数
function Foo(){…} 其实是 var Foo = new Function(…)

使用 instanceof 判断一个函数是否是一个变量的构造函数
instanceof :实例;运算符;判断对象类型
判断一个变量是否为“数组”:变量instanceof Array

4.3.原型规则和示例

1·所有的引用类型(数组、对象、函数) ,都具有对象特性,即可自由扩展属性(除了”null”意外)

var obj= {}; obj.a= 100;

var arr= []; arr.a = 100;

function fn (){}
fn.a= 100;

2·所有的引用类型(数组、对象、函数) ,都有一个 proto属性,属性值是一个普通的对象;
proto :这个叫隐式原型

console.log(obj._proto_);
console.log(arr._proto_);
console.log(fn._proto_);

3·所有的函数,都有一个prototype属性,属性值也是一个普通的对象
prototyp:这个叫显式原型

console.log(fn. prototype)

4·所有的引用类型(数组、对象、函数) ,proto属性值指向它的构造函数的” prototype “属性值

console.log (obj.proto=== object.prototype)

5.当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的proto(即它的构造函数的 prototype) 中寻找。

//构造函数
function Foo(name, age) { 
  this.name = name
}
Foo.prototype.alertName = function () {
  alert(this. name)
}

//创建示例
var f= new Foo('zhangsan')
f.printName = function (){
  console.log(this.name)
}

//测试
f.printName()  //会去11行找  结果:zhangsan
f.alertNam()  //会去第5行中找(会去它的_proto_中寻找)  结果:zhangsan
var item
for (item in f) {
          //高级浏览器已经在for in中屏蔽了来自原型的属性
          //但是这里建议大家还是加上这个判断,保证程序的健壮性
  if (f.hasOwnProperty(item)) { 
        console.log(item)
  }
}

hasOwnProperty表示是否有自己的属性。这个方法会查找一个对象是否有某个属性,但是不会去查找它的原型链

4.4.原型链

//构造函数
function Foo(name, age) { 
  this.name = name
}
Foo.prototype.alertName = function () {
  alert(this. name)
}

//创建示例
var f= new Foo('zhangsan')
f.printName = function (){
  console.log(this.name)
}

//测试
f.printName()  //会去11行找  结果:zhangsan
f.alertName()   //会去第5行中找(会去它的_proto_中寻找)  结果:zhangsan
f.toString()   //要去f._proto_._proto_中查找,也就是说首先会去第11行找然后去第5行找

image.png

4.5.instanceof(实例,运算符)

用于判断引用类型属于哪个构造函数的方法

1.f instanceof Foo的判断逻辑是:

2·f 的proto一层一层往上,能否对应到Foo.prototype

3·再试着判断f instanceof Object

4.6如何准确判断一个变量是数组类型

var arr= []
arr instanceof Array // true
typeof arr // object, typeof是无法判断是否是数组的

4.7写一个原型链继承的例子

示例1:动物继承的例子

//动物
function Animal() {
  this.eat = function () { 
    console.log('animal eat')
  }
}

//狗
function Dog() {
  this.bark = function (){ 
    console.log('dog bark')
  }
}
Dog.prototype = new Animal() 

//哈士奇
var hashiqi = new Dog()

示例2:写一个封装DOM查询的例子

function Elem(id) {
  this.elem = document.getElementById(id)
}

Elem.prototype.html = function (val) {
  var elem this.elem 
  if (val) {
    elem.innerHTML = val
    return this //链式操作
  }else {
    return elem.innerHTML
  }
}

Elem. prototype.on = function (type, fn) { 
  var elem = this.elem 
  elem.addEventListener(type, fn) 
  return this
}

var div1 = new Elem('detail-page')
        // console. log(div1.htmL())
div1.html('<p>hello imooc</p>').on('click", function (){ 
       alert('clicked')
}).html('<p>javascript</p>')

示例3:
还可以用这个方法给OBject 添加 clone方法,这个比较帅,而且还可以回顾instand of

bject.prototype.clone= function(){
 if(this == null ||  "object" != typeof this){
     return this;
 }
 if(this instanceof Number || this instanceof String || this instanceof Boolean){
     return this.valueOf();
 }

   if (this instanceof Date) {
                var copy = new Date();
                copy.setTime(this.getTime());
                return copy;
   }

 if(this instanceof Array || this instanceof Object){
     var copy = (this instanceof Array)?[]:{} ;
     for(var attr in this){
         if(this.hasOwnProperty(attr)){
               copy[attr] = this[attr]?this[attr].clone():this[attr];
         }
     }
     return copy
 }
};

4.8描述new一个对象的过程

创建一个新对象
this指向这个新对象
执行代码,即对this赋值
返回this

示例:

function Foo(name, age) {
    this.name name;
    this.age = age;
    this.class = 'class-1';
  return this //默认有这一行
}

var f = new Foo('zhangsan', 20)
    // var f1 = new Foo('lisi', 22) //创建多个对象

4.9zepto (或其他框架)源码中如何使用原型链

1·阅读源码是高效提高技能的方式

2但不能”埋头苦钻”有技巧在其中

3.慕课网搜索”zepto设计和源码分析”

5.作用域和闭包

5.1.执行上下文

console.log(a) // undefined   (变量提升)
var a = 100    //先使用后定义

fn('zhangsan')   //变量定义、函数声明,被提前抽出来了
function fn(name) { 
  age = 20
  console.log (name, age)   // 'zhangsan 20
  var age
}

范围:一段