Vue源码分析之this.message 为什么能访问到 data.message

首先我们需要知道 new Vue 背后发生了哪些事情。

我们都知道,new 关键字在 Javascript 语言中代表实例化是一个对象,而 Vue 实际上是一个类,类在 Javascript 中是用 Function 来实现的,来看一下 vue 方法,在src/core/instance/index.js 中。

1
2
3
4
5
6
7
8
9
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}
initMixin(Vue)

阅读 vue 方法可以知道 Vue 只能通过 new 关键字初始化,然后会调用 this._init 方法, 该方法在同级目录 init.js 中通过 initMixin 方法定义到 vue 原型。

Read More

Vue源码分析之构建

Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下。

通常一个基于 NPM 的项目都会有一个 package.json 文件,它是对项目的描述文件,它的内容实际上是一个标准的 JSON 对象。此类项目通常会配置 script 字段作为 NPM 的执行脚本。

Read More

Vue源码分析之 Virtual DOM

首先我们需要知道 Virtual DOM 这个概念。

Virtual DOM 这个概念,它产生的前提是浏览器中的 DOM 是很“昂贵”的,为了更直观的感受,我们可以简单的把一个简单的 div 元素的属性都打印出来,如图所示:

可以看到,真正的 DOM 元素是非常庞大的,因为浏览器的标准就把 DOM 设计的非常复杂。当我们频繁的去做 DOM 更新,会产生一定的性能问题。

Read More

Vue源码分析之Flow篇

认识 Flow

Flow 是 facebook 出品的 JavaScript 静态类型检查工具。Vue.js 的源码利用了 Flow 做了静态类型检查,所以了解 Flow 有助于我们阅读源码。

Read More

Javascript非构造函数的继承

这个系列的第一部分介绍了”封装”,第二部分介绍了使用构造函数实现”继承”。

今天是最后一个部分,介绍不使用构造函数实现”继承”。

一、什么是”非构造函数”的继承?

Read More

Javascript构造函数继承

这个系列的第一部分,主要介绍了如何”封装”数据和方法,以及如何从原型对象生成实例。

今天要介绍的是,对象之间的”继承”的五种方法。

比如,现在有一个”动物”对象的构造函数。

Read More

Javascript封装

Javascript是一种基于对象的语言,所有东西几乎都是对象。但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类)。

那么,如果我们要把”属性”(property)和”方法”(method),封装成一个对象,甚至要从原型对象生成一个实例对象,我们应该怎么做呢?

一、 生成实例对象的原始模式

Read More

Javascript-this

this是 JavaScript 语言的一个关键字,是函数生成时,在函数内部自动生成的指向函数作用域的指针。

1
2
3
function test() {
 this.a = 1;
}

函数test生成时,内部会自动有一个this指针可以使用,有四种用法。

Read More

Javascript闭包

一、作用域

要理解闭包,首先必须理解Javascript特殊的变量作用域,变量的作用域有两种:全局变量和局部变量。

Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。

1
2
3
4
5
6
7
8
9
    var a=111;

<!-- more -->

  function a1(){
    alert(a);
  }

a1(); // 111

另一方面,在函数外部无法读取函数内的局部变量。
1
2
3
4
5
6
function a1(){
    var a=999;
  }

  alert(a); // a is not defined


这里有一个地方需要注意,函数内部声明变量的时候,一定要使用let命令。如果不用的话,实际上声明了一个全局变量!
1
2
3
4
5
6
7
function a1(){
    a=111;
  }

  a1();

  alert(a); // 111

Read More

JavaScript基础

JavaScript规定了几种语言类型

Number,String,Boolean,Null,Undefined,Object,Symbol

JavaScript对象的底层数据结构是什么

四个数据属性
writable
对象属性是否可以被任意改写

enumerabel
对象属性是否可枚举,可枚举就支持for in、Object.keys、JSON.stringify方法,反之亦然。

value
对象属性的默认值

configurable
能否使用delete、能否需改属性特性、或能否修改访问器属性、,false为不可重新定义,默认值为true

两个访问器属性
get
获取对象属性值时候触发的方法

set
给对象属性赋值时候触发的方法

Symbol类型在实际开发中的应用、可手动实现一个简单的Symbol

ES6中引入了一种新的基础数据类型:Symbol,不过很多开发者可能都不怎么了解它,或者觉得在实际的开发工作中并没有什么场景应用到它,那么今天我们来讲讲这个数据类型,并看看我们怎么来利用它来改进一下我们的代码。由于Symbol是一种基础数据类型,所以当我们使用typeof去检查它的类型的时候,它会返回一个属于自己的类型symbol,而不是什么string、object之类的:
应用场景1:使用Symbol来作为对象属性名(key)
Symbol类型的key是不能通过Object.keys()或者for…in来枚举的,它未被包含在对象自身的属性名集合(property names)之中。所以,利用该特性,我们可以把一些不需要对外操作和访问的属性使用Symbol来定义。也正因为这样一个特性,当使用JSON.stringify()将对象转换成JSON字符串的时候,Symbol属性也会被排除在输出内容之外,

应用场景2:使用Symbol来替代常量
const TYPE_AUDIO = Symbol()
const TYPE_VIDEO = Symbol()
const TYPE_IMAGE = Symbol()

应用场景3:使用Symbol定义类的私有属性/方法
Symbol只能被限制在声明的js内部使用,所以使用它来定义的类属性是没有办法被模块外访问到的,达到了一个私有化的效果。

JavaScript中的变量在内存中的具体存储形式

1
2
3
4
5
var m = { a: 10, b: 20 }
var n = m;
var l = m;
n = 15;
l.a = 15

变量m存在于栈中,{ a: 10, b: 20 } 作为对象存在于堆内存中,n = m, l = m。 n = 15后切断了 与m地址值的联系故而不影响m,l.a = 15 会改变m.a 的值。

基本类型对应的内置对象,以及他们之间的装箱拆箱操作

还是拿最开始的例子 var s1 = “abc”;var s2 = s1.indexOf(“a”);
变量s1是一个基本类型值,它不是对象,它不应该有方法。但是js内部为我们完成了一系列处理(即装箱),使得它能够调用方法。
拆箱:将引用类型对象转换为对应的值类型对象,它是通过引用类型的valueOf()或者toString()方法来实现的。
console.log( typeof s1 ); //object console.log( typeof objStr.valueOf() ); //string console.log( typeof objNum.toString() ); // string

理解值类型和引用类型

JS基本类型与引用类型知多少
1、JavaScript值类型和引用类型有哪些
(1)值类型(基本类型):数值(number)、布尔值(boolean)、null、undefined、string(在赋值传递中会以引用类型的方式来处理)。

(2)引用类型:对象、数组、函数。

2、如何理解值类型和引用类型
之前看到一个比喻,觉得非常贴切,想要和大家分享一下:用“连锁店”和“连锁店钥匙”来理解。
(1)值类型:变量的交换等于在一个新的地方按照连锁店的规范标准(统一店面理解为相同的变量内容)新开一个分店,这样新开的店与其它旧店互不相关、各自运营。
(2)引用类型:变量的交换等同于把现有一间店的钥匙(变量引用地址)复制一把给了另外一个老板,此时两个老板同时管理一间店,两个老板的行为都有可能对一间店的运营造成影响。

null和undefined的区别

最初设计
JavaScript的最初版本是这样区分的:null是一个表示”无”的对象,转为数值时为0;undefined是一个表示”无”的原始值,转为数值时为NaN。
目前的用法
但是,上面这样的区分,在实践中很快就被证明不可行。目前,null和undefined基本是同义的,只有一些细微的差别。

null表示"没有对象",即该处不应该有值。典型用法是:

(1) 作为函数的参数,表示该函数的参数不是对象。

(2) 作为对象原型链的终点。


Object.getPrototypeOf(Object.prototype)
// null

undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:

(1)变量被声明了,但没有赋值时,就等于undefined。

(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。

(3)对象没有赋值的属性,该属性的值为undefined。

(4)函数没有返回值时,默认返回undefined。

至少可以说出三种判断JavaScript数据类型的方式,以及他们的优缺点,如何准确的判断数组类型

1、typeof:(可以对基本类型做出准确的判断,但对于引用类型,用它就有点力不从心了)
2、instanceof 判断对象和构造函数在原型链上是否有关系,如果有关系,返回真,否则返回假
3、constructor:查看对象对应的构造函数,constructor 在其对应对象的原型下面,是自动生成的。当我们写一个构造函数的时候,程序会自动添加:构造函数名.prototype.constructor = 构造函数名
4、Object.prototype.toString(可以说不管是什么类型,它都可以立即判断出)

可能发生隐式类型转换的场景以及转换原则,应如何避免或巧妙应用

1, “+”“-”运算符
2,语句中存在的隐式类型转换,会在判断时转换为Boolean类型;
3, alert时存在的隐式类型转换

1
2
3
4
String.prototype.fn = function(){return this};
var a = 'hello';
alert(typeof a.fn()); //-->object
alert(a.fn()); //-->hello

出现小数精度丢失的原因,JavaScript可以存储的最大数字、最大安全数字,JavaScript处理大数字的方法、避免精度丢失的方法

最大安全数字:即2的53次方,为9007199254740992。如果超过这个值,那么js会出现不精确的问题。解决精度丢失的问题,NPM上有许多支持JavaScript和Node.js的数学库,比如math.js,decimal.js,D.js等等

Read More