js数据类型
js数据类型:字符串、数字、布尔、数组、对象、Null、Undefined
原始数据类型值 primitive type,比如Undefined,Null,Boolean,Number,String。
引用类型值,也就是对象类型 Object type,比如Object,Array,Function,Date等。
这两者在声明变量的时候有什么区别
- 原始值:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。这是因为这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 – 栈中。这样存储便于迅速查寻变量的值。
- 引用值:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。
复制变量时的不同
- 复制变量时的不同原始值:在将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。
- 引用值:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。(这里要理解的一点就是,复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量罢了)
var a=b=obj{}
//如果a改变obj中的一个属性则b也变
//如果a重新指向另一个obj2, 并且改变obj2则b不变
复制代码
== 跟 === 的区别
"==="叫做严格运算符,"=="叫做相等运算符
===有以下规则
- 如果两个值的类型不同,直接返回false。这个效率比==高,==需要转换
- 同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false。
- 两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个对象。
- undefined 和 null 与自身严格相等。(null === null , undefined === undefined)
==有以下规则
- 相等运算符在比较相同类型的数据时,与严格相等运算符完全一样。
- 原始类型的数据会转换成数值类型再进行比较。字符串和布尔值都会转换成数值。
- 对象(这里指广义的对象,包括数值和函数)与原始类型的值比较时,对象转化成原始类型的值,再进行比较。
- undefined和null与其他类型的值比较时,结果都为false,它们互相比较时结果为true (这个没找见原因, 好像是node设计时写死的) 下面看下代码:
'' == '0' // false
0 == '' // true Number('') 将会返回0
0 == '0' // true
false == 'false' // false false返回0 ‘false’返回NAN
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true
复制代码
var a = [1,2,3];
var b = [1,2,3];
var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };
var e = "text";
var f = "te" + "xt";
a == b // false //a跟b两个NaN
a === b // false //a,b 不属于两个对象
c == d // false
c === d // false
e == f // true 类型相等 值相等
e === f // true
"abc" == new String("abc") // true 将==后面的对象转换为string类型 再比较
"abc" === new String("abc") // false 下面会介绍new是什么含义
复制代码
怎样将primitive type 转换为引用传递
解决办法应该只能转成对象了,当然, 也可以挂再global上, 但是感觉没必要。
var ref = { value: 1 };
function Foo(x) {
x.value++;
}
Foo(ref)
复制代码
js中的引用到底跟c有什么区别
- c指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元。
- c引用:跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已(pass by reference) 所以在c中, 如果引用中的值变了, 那么原来的值也会变。
- js引用:对象的值得传递并不是按引用传递。其实,按共享传递 (call by sharing)。 该策略的重点是:调用函数传参时,函数接受对象实参引用的副本(既不是按值传递的对象副本,也不是按引用传递的隐式引用)。 它和按引用传递的不同在于:在共享传递中对函数形参的赋值,不会影响实参的值。
为什么0.1+0.2==0.3 是错的
0.1 = 0.0001 1001 1001 1001…
0.2 = 0.0011 0011 0011 0011…
相加之后为:0.0100110011001100110011001100110011001100110011001100
复制代码
将结果转换十进制就是0.300...4了。 出现这种结果是因为js中没有浮点型, 因此在做计算的时候不会像c一样进行四舍五入(c的printf是六位) 解决方法
parseFloat((0.1 + 0.2).toFixed(2)) === 0.3
//toFixed onvert it to a number with 2 decimal
复制代码
new 跟 this
当出现new关键字的时候计算机做了什么
- A new object will be created in the memory
- The scope of that object will be passed to the function; So the this keyword will refer to that object.
- The newly created object will be returned.
this 关键字
在绝大多数情况下,函数的调用方式决定了this的值。this在严格模式和非严格模式之间也会有一些差别。
- 全局执行上下文中(在任何函数体外部)this都指代全局对象。也就是一个js文件, 不在函数里面写this, 而是在函数外部, this指向global。
a.js
console.log(this === global);//true
复制代码
- 在函数内部,this的值取决于函数被调用的方式。
function f1(){
return this;
}
f1() === global;
复制代码
准确的来说, this指向当前函数的拥有者, f1 的拥有者是global。
call() 关键字
call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)
fun.call(thisArg, arg1, arg2, ...)
复制代码
- thisArg: 在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。
- 返回值: 返回值是你调用的方法的返回值,若该方法没有返回值,则返回undefined。
实际中的例子:
function Product(name, price) {
this.name = name||'papanda';
this.price = price||'papanda';
if (price < 0) {
throw RangeError('Cannot create product ' +this.name + ' with a negative price');
}
}
//如果直接跑函数: Product() 则globa会挂上name跟price属性, 并且值为'papanda', 因为Produc的函数拥有者为global
//加上new关键字: let product = new Product('banana','0.1'), 这时候global没有name跟price属性, product:{ name: 'banana', price: '0.1' }
function Food(name, price) {
Product.call(this, name, price); //this指向global
this.category = 'food';
}
//等同于
function Food(name, price) {
this.name = name;
this.price = price;
if (price < 0) {
throw RangeError('Cannot create product ' + this.name + ' with a negative price');
}
this.category = 'food';
}
//只使用上面的Food函数
//直接跑函数: Food('apple', '0.2') global会多加一个属性 category
//使用new: let myFood = new Food('apple', '0.4') 返回Food { name: 'apple', price: '0.4', category: 'food' }, global并没有改变
复制代码
var let const之间的区别
The difference is scoping. var is scoped to the nearest function block and let is scoped to the nearest enclosing block, which can be smaller than a function block. Both are global if outside any block.
在global中的区别
They are very similar when used like this outside a function block.However, global variables defined with let will not be added as properties on the global window object like those defined with var.
let me = 'go'; // globally scoped
var i = 'able'; // globally scoped
//他俩作用域一样但是me不会挂载在global上, i会挂载在global
复制代码
在函数上的区别
They are identical when used like this in a function block. 作用域都是function函数
在block的区别
Here is the difference. let is only visible in the for() loop and var is visible to the whole function.
function allyIlliterate() {
//tuce is *not* visible out here
for( let tuce = 0; tuce < 5; tuce++ ) {
//tuce is only visible in here (and in the for() parentheses)
//and there is a separate tuce variable for each iteration of the loop
}
//tuce is *not* visible out here
}
function byE40() {
//nish *is* visible out here
for( var nish = 0; nish < 5; nish++ ) {
//nish is visible to the whole function
}
//nish *is* visible out here
}
复制代码
Redeclaration 重复声明
Assuming strict mode, var will let you re-declare the same variable in the same scope. On the other hand, let will not:
'use strict';
console.log(me)//SyntaxError....
let me = 'foo';
let me = 'bar'; // SyntaxError: Identifier 'me' has already been declared
'use strict';
consol.log(me); //me是undefined
var me = 'foo';
var me = 'bar'; // No problem, `me` is replaced.
复制代码
var 在声明之后会提升到scope中的最上面,但是不会用到下面的值, 上面的值是undefined, let则没有. const : 跟let一样, 但是不能修改
const name1 = value1 [, name2 = value2 [, ... [, nameN = valueN]]];
复制代码
value1 可以是任何有效的表达式, 或者函数。
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its parameters) can be altered.
modules
在node中每一个文件被当做分离的模块,
foo.js
const circle = require('./circle.js');
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`);
复制代码
circle.js
const { PI } = Math;
//Variables local to the module will be private, because the module is wrapped in a function by Node.js , PI是私有变量
exports.area = (r) => PI * r ** 2;
//Functions and objects are added to the root of a module by specifying additional properties on the special exports object.
exports.circumference = (r) => 2 * PI * r;
复制代码
module wrapper
(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
});
复制代码
JavaScript中的立即执行函数表达式
moudle 简介
require,import区别
if (stat){statement1}else{statement2}
当stat为false,null, undefined, '', 0,NaN进入statement1,负责,进入statement2.