var s = "woaibeijing";
dd = s.indexOf("e")+"<br>";//从前往后
ee = s.indexOf("e",3)+"<br>";//可选参数,从第几个字符往后查找
ff = s.lastIndexOf("e")+"<br>";//从后往前
gg = s.lastIndexOf("e",3)+"<br>"; //可选参数,从第几个字符往前查找
hh = s.lastIndexOf("H")+"<br>";
document.write(dd);
document.write(ff);
document.write(ee);
document.write(gg);
document.write(hh);
另外,indexof()和lastindexof()的用法推荐查看这篇文章。https://www.jb51.net/article/44921.htm
JS中的indexOf和lastIndexOf是处理字符串的一个非常好用的函数,下面对它们的定义、用法、注意事项以及使用建议分别作介绍。
1、strObj.indexOf(subString[, startIndex])
功能:返回源字符串内第一次出现指定子字符串的首个字符在源字符串中的索引值(源字符串内第n个字符的索引值为n-1),是整数。
参数含义:
strObj是源字符串,必选项。
subString是在源字符串对象中查找的子字符串,必选项。
startIndex是开始索引值,indexOf函数是从源字符串的索引值为startIndex的字符(即第startIndex+1个字符)开始查找,可选项。省略时,从源字符串索引值为0的字符(即第1个字符)开始查找。
实例分析:
用法1(不指定startIndex值):var i="huoshandao.com".indexOfOf("a"):则i=5
相当于var i="huoshandao.com".indexOf("a",0)
用法2(指定startIndex值):var i="huoshandao.com".indexOf("a",6):则i=8
提示:可以用alert(i);语句测试结果,以下例子也一样。
注意事项
1)strObj既可以是字符串,也可以是字符串变量。
[例子]
strObj为字符串:var i="huoshandao.com".indexOf("."):
strObj为字符串变量:var str="huoshandao.com";var i=str.indexOf(".");
2)subString不能为空字符串,如果为空字符串,返回值为0,但可以是空格。
[例子]
subString为空字符串:var i="huo shan dao".indexOf(""):则i=0
subString为空格字符串:var i="huo shan dao".indexOf(" "):则i=3
3)第1个字符的startIndex值是0,是最小索引值;第2个字符的startIndex值是1;最后一个字符的startIndex值则是源字符串长度减1,是最大索引值。
4)如果没有找到子字符串,则返回 -1。
[例子]
var i="huoshandao.com".indexOf("huosan"):则i=-1
5)如果startIndex是负数,则相当于startIndex等于0的情况。如果它大于最大索引值,则相当于startIndex等于最大索引值的情况。
[例子]
startIndex为负数: var i="huoshandao.com".indexOf(".",-3);则i=10
与var i="huoshandao.com".indexOf(".",0);结果一样
startIndex大于等于字符串长度:var i="huoshandao.com_".indexOf("_",16);则i=-1
与var i="huoshandao.com_".indexOf("_",14);i=14
2、strObj.lastIndexOf(subString[, startIndex])
indexOf 函数是从左向右查找,但实际应用中我们有时想得到从右向左出现某个字符或字符串的首个字符索引值,针对这种情况,JS给出另外一个函数 lastIndexOf来解决这个问题,使用方法和indexOf相似,只是它从右向左查找而已,具体就不再重复,简单举几个例子,和indexOf作比 较:
例1:var i="huo.shan.dao.com".lastIndexOf(".");则i=12而var i="huo.shan.dao.com".indexOf(".");的i=3
例2:var i="huoshandao.com_".lastIndexOf("_",16);则i=14而var i="huoshandao.com_".indexOf("_",16);则i=-1
3、使用建议
为了避免出乎意料的结果,除非有特殊用途,建议遵循以下原则:
1、startIndex为非负数,并且不大于最大索引值。如果startIndex是变量,要先判断其值是否在这个范围内。
2、如果子字符串subString是变量的话,要先判断其是否为空再使用indexOf或lastIndexOf函数。
3、输入子字符串时要特别注意全角字符和半角字符的区别。
4、注意indexOf和lastIndexOf里面的大小写,JS对大小写非常敏感。建议用Dreamweaver编程,如果函数名大小写写错的话,函数颜色是黑色,写对的话则会变成另外一种颜色。
您可能感兴趣的文章:- javascript数据类型基础示例教程
- JavaScript基础语法与数据类型介绍
- js中基础的数据类型详解
- javascript基础之数据类型详解
- JavaScript的基础语法和数据类型详解
- JavaScript 变量,数据类型基础实例详解【变量、字符串、数组、对象等】
- JavaScript基础心法 数据类型
- 浅谈js基础数据类型和引用类型,深浅拷贝问题,以及内存分配问题
- Javascript基础教程之数据类型转换
- Javascript基础教程之数据类型 (布尔型 Boolean)
- Javascript基础教程之数据类型 (数值 Number)
- JavaScript基础知识之数据类型
- javascript 基础篇2 数据类型,语句,函数
- javascript基础数据类型转换教程示例

JavaScript — 数据类型之 String字符串
数据类型指的就是字面量的类型
JavaScript 中有八种基本的数据类型(前七种为基本数据类型,也称为原始类型,而 object 为复杂数据类型)。
- number用于任何类型的数字:整数或浮点数,在
±(253-1)
范围内的整数。 bigint
用于任意长度的整数。string
用于字符串:一个字符串可以包含 0 个或多个字符,所以没有单独的单字符类型。boolean
用于 true
和 false
。null
用于未知的值 —— 只有一个 null
值的独立类型。undefined
用于未定义的值 —— 只有一个 undefined
值的独立类型。symbol
用于唯一的标识符。object
用于更复杂的数据结构。
String字符串
1.引号
在JS中字符串需要使用引号引起来,同样的引号不能嵌套(双引号不能直接嵌套双引号)
在 JavaScript 中,有三种包含字符串的方式。
- 双引号:" Hello "
- 单引号:' Hello '
- 反引号:` Hello `
双引号和单引号都是简单引用,在 JavaScript 中两者几乎没有什么差别。
反引号是 功能扩展 引号。它们允许我们通过将变量和表达式包装在 ${...} 中,来将它们嵌入到字符串中。例如:
let name = "John";
// 嵌入一个变量
alert( `Hello, ${name}!` ); // Hello, John!
// 嵌入一个表达式
alert( `the result is ${1 + 2}` ); // the result is 3
${...} 内的表达式会被计算,计算结果会成为字符串的一部分。可以在 ${...} 内放置任何东西:变量,或者算数表达式,或者其他一些更复杂的内容。
另外,反引号允许字符串跨行:(单引号和双引号则不可以)
let nameList = `Names:
* Tom
* Tony
* Mary
`;
alert(nameList); // 多行的名单

2.转义字符
在字符串中我们可以使用 \ 作为转义字符,当表示一些特殊符号时可以使用 \ 进行转义
例如:
let nameList = "Names:\n Tom\n Tony\n Mary";
alert(nameList); // 一个多行的名单

转义字符
符号 | 表示含义 |
\n | 换行 |
\r | 回车:不单独使用。Windows文本文件使用两个字符\r\n的组合来表示换行 |
\' , \" | 引号 |
\\ | 反斜线 |
\t | 制表符 |
\b, \f, \v | 退格、换页、垂直标签——为了兼容性,现在已经不使用 |
\xXX | 具有给定十六进制 Unicode XX 的 Unicode 字符,例如:'\x7A' 和 'z' 相同。 |
\uXXXX | 以 UTF-16 编码的十六进制代码 XXXX 的 unicode 字符,例如 \u00A9 —— 是版权符号 © 的 unicode。它必须正好是 4 个十六进制数字。 |
\u{X...XXXXXX} | 具有给定 UTF-32 编码的 unicode 符号。一些罕见的字符用两个 unicode 符号编码,占用 4 个字节。这样我们就可以插入长代码了。 |
3.字符串长度
length 属性表示字符串长度
举个例子:
alert( `My\n`.length ); // 3
\n 是一个单独的“特殊”字符,所以长度是3。
查看字符串长度可以调用 str.length 属性
4.访问字符
要获取在 pos 位置的一个字符,可以使用方括号 [ pos ] 或者调用 str.charat(pos) 方法。第一个字符从零位置开始:
let str = `Hello`;
// 第一个字符
alert( str[0] ); // H
alert( str.charat(0) ); // H
// 最后一个字符
alert( str[str.length - 1] ); // o
如果没有找到字符,[]返回 undefined,而 charat 返回一个空字符串
另外,可以使用 for...of 遍历字符 :
for (let char of "Hello") {
console.log(char);
}

字符串中的单个字符是不可以被直接更改的!!!
5. 改变大小写
可以使用 toLowerCase() 和 toupperCase() 的方法来改变大小写
举个例子:
alert( 'Interface'.toupperCase() ); // INTERFACE
alert( 'Interface'.toLowerCase() ); // interface
也可以使字符串中的一个字符改变大小写
再举个例子:
alert( 'Interface'[0].toLowerCase() ); // 'i'
6.查找子字符串
(1).str.indexOf()
str.indexOf(substr,pos)
它从给定位置 pos 开始,在 str 中查找 substr,如果没有找到,则返回 -1,否则返回匹配成功的位置。
let str = 'Widget with id';
alert( str.indexOf('Widget') ); // 0,因为 'Widget' 一开始就被找到
alert( str.indexOf('widget') ); // -1,没有找到,检索是大小写敏感的
alert( str.indexOf("id") ); // 1,"id" 在位置 1 处(……idget 和 id)
可选的第二个参数 "pos" 允许我们从给定的起始位置开始检索。
例如,“id” 第一次出现的位置是 1。查询下一个存在位置时,我们从 2 开始检索:
let str = 'Widget with id';
alert( str.indexOf('id', 2) ) // 12
还有一个类似的方法 str.lastIndexOf(substr,pos) ,它从字符串的末尾开始搜索到开头。
它会以相反的顺序列出这些事件。
(2).includes、startsWith、endsWith
str.includes(substr,pos) 根据 str 中是否包含 substr 来返回 true/false。
如果需要检测匹配,但不需要它的位置,那么就可以选择这种方法
举个例子:
alert( "Widget with id".includes("Widget") ); // true
alert( "Hello".includes("Bye") ); // false
str.includes 的第二个可选参数是开始搜索的起始位置
再举个例子:
alert( "Midget".includes("id") ); // true
alert( "Midget".includes("id", 3) ); // false, 从位置 3 开始没有 "id"
方法 str.startsWith(substr) 和 str.endsWith(substr) 表示字符串是否以substr开头或结尾
再再举个例子:
alert( "Widget".startsWith("Wid") ); // true,"Widget" 以 "Wid" 开始
alert( "Widget".endsWith("get") ); // true,"Widget" 以 "get" 结束
7.获取子字符串

(1).str.slice(start [, end])
返回字符串从 start 到(但不包括)end 的部分
举个例子:
let str = "stringify";
alert( str.slice(0, 5) ); // 'strin',从 0 到 5 的子字符串(不包括 5)
alert( str.slice(0, 1) ); // 's',从 0 到 1,但不包括 1,所以只有在 0 处的字符
如果没有第二个参数,slice 会一直运行到字符串末尾:
let str = "stringify";
alert( str.slice(2) ); // 从第二个位置直到结束
start / end 也有可能是负值。它们的意思是起始位置从字符串结尾计算:
let str = "stringify";
// 从右边的第四个位置开始,在右边的第一个位置结束
alert( str.slice(-4, -1) ); // 'gif'
(2). str.substring(start [, end])
返回字符串在 start 和 end 之间的部分,与slice几乎相同,但它允许start大于end,而且不支持负的参数。
let str = "stringify";
// 这些对于 substring 是相同的
alert( str.substring(2, 6) ); // "ring"
alert( str.substring(6, 2) ); // "ring"
// ……但对 slice 是不同的:
alert( str.slice(2, 6) ); // "ring"(一样)
alert( str.slice(6, 2) ); // ""(空字符串)
(3).str.substr(start [, length])
返回字符串从 start 开始的给定 length 的部分。
与以前的方法相比,这个允许我们指定 length 而不是结束位置:
let str = "stringify";
alert( str.substr(2, 4) ); // 'ring',从位置 2 开始,获取 4 个字符
第一个参数可能是负数,从结尾算起:
let str = "stringify";
alert( str.substr(-4, 2) ); // 'gi',从第 4 位获取 2 个字符
两种字符串函数:
str.trim()
—— 删除字符串前后的空格 (“trims”)。str.repeat(n)
—— 重复字符串 n
次。

Javascript——字符串数据类型(String)
了解字符串
- 由引号(双引号、单引号、反引号)包裹的值叫做字符串
- 字符串在使用时自动转换为复杂数据类型,使用完后自动转为基本数据类型
- 当使用
字符串.xxx
操作语法时,字符串转为复杂数据类型,在堆空间开辟一块空间,将每个字符按照索引进行排列,就可以访问里面的数据,使用结束后,转为基本数据类型,在堆空间内开辟的空间也自动销毁
字符串的创建方法
- 字面量创建方法:
var 字符串名=''''
- 内置构造函数创建方法:
var 字符串名=new String('''')
创建字符串初始化数据
- 字面量创建方法:在
var str = ''hello world''
内直接写数据即可 - 内置构造函数创建方法:
var str = new String(''hello world'')
内写数据即可
其他数据类型转换为字符串数据类型方法
- 语法:
变量.toString()
转换规则:
- 可将数值、布尔值、字符串转为字符串类型
- undefined 和 null无法转为字符串类型
字符串的length属性
- 字符串的length属性表示一个字符串的长度;使用
字符串.length
可获取一个字符串的长度;字符串无法设置自己的长度;在字符串中,空格也算一个字符 - 通过
字符串名[索引]
可获取指定下标的字符,但是不能对某一个字符进行修改,因为字符串时基本数据类型,所以只能重新赋值覆盖之前的数据
字符编码
- ASCII 码:一共128个,键盘上每个按键对应一个二进制码
- Unicode 码:国际编码,目前使用的为UTF-8
- GBK 码:中文编码,包含所有汉字
- 不同的编码,同一个码值所对应的内容也不一样
字符串操作方法
语法:字符串名.charAt(索引)
返回值:索引位置存在,返回对应字符,索引位置不存在返回空
使用:str.charAt(12)
语法:字符串名.charCodeAt(索引)
返回值:索引位置字符的编码,索引位置不存在返回NaN
使用:str.charCodeAt(12)
语法:字符串名.substr(开始截取索引,截取个数)
参数:不写参数默认全部截取,参数二不写截取到字符串末尾
返回值:截取到的字符串
使用:str.substr(1,5)
语法:字符串名.substring(开始截取索引,结束截取索引)
参数:不写参数默认全部截取,参数二不写截取到字符串末尾
返回值:截取到的字符串
使用:str.substr(1,5)
语法:字符串名.toLowerCase()
返回值:转换后的字符串
使用:str.toLowerCase()
语法:字符串名.toUpperCase()
返回值:转换后的字符串
使用:str.toUpperCase()
语法:字符串名.replace(''需要进行替换的字符串'',''替换的字符串内容'')
注意点:参数一字符串中没有时,不进行替换,遇到第一个满足条件的内容替换后不再往下替换
返回值:替换后的字符串
使用:str.replace(''H'',''h'')
语法:字符串名.concat(''拼接的字符串''···)
参数:可以直接写字符串,也可以写字符串变量
返回值:替换后的字符串
使用:str.concat(str2,'' 世界'')
语法:字符串名.slice(开始索引,结束索引)
参数:索引写负整数表示从 length + 负整数位置
返回值:截取到的字符串
使用:str.slice(5,10)
语法:字符串名.split(''切割的符号'',切割个数)
参数:参数1不写时返回整个字符串,写空字符串表示一位一个进行切割;参数2表示切割的个数,默认为全部进行切割
返回值:切割后一个存储字符的一个数组
使用:str.split('' '',11)
- 从字符串开始位置向后查找字符串片段在字符串中首次出现的位置
语法①:字符串.indexOf(''字符串片段'')
语法②:字符串.indexOf(''字符串片段'', 开始索引)
返回值:字符串中存在该字符串片段,返回对应索引,字符串中不存在该字符串片段,返回-1
使用:str.indexOf(''H'')
str.indexOf(''H'',5)
- 从字符串结束位置向前查找字符串片段在字符串中首次出现的位置
语法①:字符串.lastIndexOf(''字符串片段'')
语法②:字符串.lastIndexOf(''字符串片段'', 开始索引)
返回值:字符串中存在该字符串片段,返回对应索引,字符串中不存在该字符串片段,返回-1
使用:str.lastIndexOf(''H'')
str.lastIndexOf(''H'',5)
语法:字符串.includes(''字符串片段'')
返回值:字符串中存在该字符串片段,返回 true,字符串中不存在该字符串片段,返回false
使用:str.includes(''w'')
语法:字符串.search(''字符串片段'')
参数:参数可以写正则表达式
返回值:字符串中存在该字符串片段,返回对应索引,字符串中不存在该字符串片段,返回-1
使用:str.search(''w'')
语法:字符串.match(''字符串片段'')
参数:参数一般写正则表达式
返回值:一个存储查找到匹配的字符串片段的数组
使用:str.match(''w'')
语法:字符串.trim()
返回值:去除首尾空格后的字符串
使用:str.trim()
语法:字符串.trimStart()
返回值:去除头部空格后的字符串
使用:str.trimStart()
语法:字符串.trimEnd()
返回值:去除尾部空格后的字符串
使用:str.trimEnd()
语法:字符串.padStart(目标长度, ''填充字符'')
参数:参数1:目标长度小于字符串长度时,方法无意义;目标长度大于或等于时,使用填充字符进行填充;参数2:可以是多个字符,也可以只有一个字符,多个字符超出长度后,后面不能补齐的字符被丢弃
返回值:补齐后的字符串
使用:str.padStart(11,''世界'')
语法:字符串.padEnd(目标长度, ''填充字符'')
参数:参数1:目标长度小于字符串长度时,方法无意义;目标长度大于或等于时,使用填充字符进行填充;参数2:可以是多个字符,也可以只有一个字符,多个字符超出长度后,后面不能补齐的字符被丢弃
返回值:补齐后的字符串
使用:str.padEnd(11,''世界'')
语法:字符串.startsWith(''字符串片段'')
返回值:如果是以该字符串片段开始返回 true ,如果不是以该字符串片段开始返回 false
使用:str.startsWith(''世界'')
语法:字符串.endsWith(''字符串片段'')
返回值:如果是以该字符串片段开始返回 true ,如果不是以该字符串片段开始返回 false
使用:str.endsWith(''世界'')

JavaScript基础(一) 数据类型
动态类型
JavaScript 是一种弱类型或者说动态语言。这意味着你不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。
数据类型
最新的 ECMAScript
标准定义了 7 种数据类型:
typeof 检测数据类型
typeof
用来检测给定变量的数据类型,返回下列某个字符串:
有这样一道题目,考察 typeof
返回值类型。
typeof(typeof(new Date())) //string
但是在实际项目中,typeof
也只是用来判断变量是undefined
和 function
。因为很多类型不能精确的判断出来,例如:
Value |
function |
typeof |
"foo" |
String |
string |
new String("foo") |
String |
object |
1.2 |
Number |
number |
new Number(1.2) |
Number |
object |
true |
Boolean |
boolean |
new Boolean(true) |
Boolean |
object |
new Date() |
Date |
object |
new Error() |
Error |
object |
[1,2,3] |
Array |
object |
new Array(1, 2, 3) |
Array |
object |
new Function("") |
Function |
function |
/abc/g |
RegExp |
object |
new RegExp("meow") |
RegExp |
object |
{} |
Object |
object |
new Object() |
Object |
object |
注意
typeof /s/ ===function; // Chrome 1-12 , 不符合 ECMAScript 5.1
typeof /s/ === object; // Firefox 5+ , 符合 ECMAScript 5.1
由上得出结论,当使用检测结果是object
或function
时,我们并不能看出实际的数据类型。
推荐使用 Object.prototype.toString()
,结合call
去实现对变量类型的精准判断。
Object.prototype.toString.call(null); //”[object Null]”
Object.prototype.toString.call(undefined); //”[object Undefined]”
Object.prototype.toString.call(“abc”); //”[object String]”
Object.prototype.toString.call(123); //”[object Number]”
Object.prototype.toString.call(true); //”[object Boolean]”
简单封装如下:
function _typeof(obj){
if(typeof obj == object || typeof obj == function){
var type =Object.prototype.toString.call(obj).split("")[1].toLowerCase();
return type.match(/[a-z]/g).join(""); //正则去除字符串的]
}
return typeof obj;
}
上面代码在标准浏览器中可以完全兼容,但是IE6
(虽然现在不必兼容,也要了解下)中,却会出现以下问题:
_typeof(null); //object
_typeof(undefined); //object
原因在于IE6下
Object.prototype.toString.call(undefined); //”[object Object]”
Object.prototype.toString.call(null); //”[object Object]”
所以要先添加判断,使用String()
对象将 undefined
,null
转为字符串。代码如下:
function _typeof (obj){
//注意到这里是 == 而不是 === ,
//undefined 值是派生自 null 值的,所以null == undefined 返回true
if(obj == null){
return String(obj)
}
if(typeof obj == "object"; || typeof obj == "function"){
var type =Object.prototype.toString.call(obj).split(" ")[1].toLowerCase();
return type.substring(0,type.length-1);
}
return typeof obj;
}
String()
函数遵循下列转换规则:
如果值有 toString()
方法,则调用该方法(没有参数)并返回相应的结果;
如果值是 null
,则返回"null"
;
如果值是 undefined
,则返回"undefined"
。
这样对 typeof
的扩展就封装好了。代码还有优化空间,这里不再继续。
Jquery
已经实现了类型检测的封装,jquery.type()
的内部实现如下:
//实例对象是能直接使用原型链上的方法的
var class2type = {};
var toString = class2type.toString;
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
$.type = function( obj ) {
//如果是null或者undefined,直接转成String返回
//注意到这里是==而不是===,
//undefined 值是派生自 null 值的,所以null == undefined 返回true
if ( obj == null ) {
return String( obj );
}
//当typeof 返回 object或function, 进入core_toString
return typeof obj === "object" || typeof obj === "function" ?
class2type[ core_toString.call(obj) ] || "object":
typeof obj;
}
Undefined
Undefined
类型只有一个值,即特殊的 undefined
。在使用 var
声明变量但未对其加以初始化时,这个变量的值就是 undefined
,例如:
var foo;
alert(foo == undefined); //true
undefined
表示"缺少值",就是此处应该有一个值,但是还没有定义。
典型用法是:
变量被声明了,但没有赋值时,就等于 undefined
。
调用函数时,应该提供的参数没有提供,该参数等于 undefined
。
对象没有赋值的属性,该属性的值为 undefined
。
函数没有返回值时,默认返回 undefined
。
var name;
alert(name) // undefined
function f(x){console.log(x)}
f() // undefined
var o = new Object();
alert(o.p) // undefined
var x = f();
alert(x) // undefined
Null
Null
类型是第二个只有一个值的数据类型,这个特殊的值是 null
。
如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为 null
。
null
有时会被当作一种对象类型,但是这其实只是语言本身的一个bug,即对 null
执行 typeof null
时会返回字符串"object"
。
原理是这样的,不同的对象在底层都表示为二进制,在JavaScript
中二进制前三位都为0
的话会被判断为object
类型,null
的二进制表示是全0
,自然前三位也是0
,所以执行 typeof
时会返回“object”
。——《你不知道的JavaScript》
使用null
的情况:
1.DOM
,试图获取一个不存在的元素返回一个null
值,而不是undefined
。
2.初始化一个对象的值,一般设为null
。
3.通过分配null
值,有效地清除引用,并假设对象没有引用其他代码,指定垃圾收集,确保回收内存。
var table = document.getElementById("table");
console.log(table); // null
var obj = null; //初始化对象
window.onload = function(){
var el = document.getElementById("id");
var id = el.id; //解除循环引用
el.onclick = function(){
alert(id);
}
el = null; // 将闭包引用的外部函数中活动对象清除
}
Boolean
Boolean
类型是常用的一种类型,只有两个字面值:true
和 false
。
注意:字面值区分大小写,True 和 False 不是 Boolean 值。
经常遇到就是其他数据类型转为boolean的问题,只要遵循一个原则:
当值为""
(空字符串)、0
、NaN
、null
、undefined
时,都转为false
,其他情况都为true
。

JavaScript基础之数据类型
JavaScript是脚本语言
计算机语言可以分为三类,机器语言、汇编语言、高级语言。高级语言又可以简单分为解释类和编译类。这个知道就够了。
机器语言: 计算机所能识别的二进制语言,一般也不会直接拿来用于编程,无法理解且难以记忆
汇编语言: 底层程序可以直接理解的指令,一般是英文缩写,一般简短、简单(功能简单),只能做一些非常细微的操作,复杂的操作往往伴随着大量的指令,我等一般接触不多
高级语言: 简单理解,我们平常接触到的听说过的基本都是高级语言。高级语言又分为解释类和编译类。解释类语言和编译类语言都需要转换成机器语言才能被机器执行,区别在于转换的时间,解释类语言也就是一般通称的脚本语言,依赖于解释器,边解释边执行,编译类是全部转换(编译)好了,打包拿出去执行。JavaScript不需要编译,但是需要在自己的解释器上执行,比如我们常用的浏览器。
内存、地址、指针
有过C语言基础的人一定听说过这么一句话,指针是C语言的灵魂。但是似乎在JavaScript中,并没有接触过所谓的指针的概念,但JavaScript的解释器(JavaScript引擎)不管用什么编写,有的是C,有的是C++,也或者是Java,甚至是JavaScript自举实现的JavaScript解释器(元循环虚拟机),都逃不脱内存和指针,在JaVaScript中也有体现。所以了解下这些概念,对于学习JavaScript,总归是有好处的。
计算机内存最小单位是位,8位一个字节(byte),实际计算机中,内存最小单位是字节(byte),通俗来讲,可以把内存条当做内存,计算机运行时临时存储数据的地方。也可以把它看做一个大的图书馆,有无数个格子,每个格子都有一个编号,这个编号就是地址,每个地址对应唯一一段内存。我们通常所说的系统为数据分配一段内存
,也就是给这个数据分配格子,一个格子放不下,那就给分三五个格子来放。而指针则是固定占用4个格子(4byte),里面放的不是真实的数据,而是放的另外一段内存的地址,只是个地址。
原始数据类型
Undefined、Null、Boolean、Number、String和Symbol(ES6)
原始数据类型实在太简单,所以只简单划几个重点:
原始数据类型不可改变 原始数据类型一个非常重要的特征就是不可改变
。原始数据类型是保存在栈中的,一旦声明一个变量 var a = "老李";
解释器会申请一块内存来存储"老李"
,a是标识符(标识符存储的是内存地址,但在经过解释/编译后会就不需要了),如果此时其他操作尝试修改a,比如a += ",你好!";
,此时打印a,虽然会输出"老李,你好!";
但是实际这其中改变的是a的地址指向,解释器会为"老李,你好!"
申请一片新的内存来存储,a中存储的指向改变了,原先的"老李"
所占用的内存会被回收但本身并未被改变。
原始数据类型是按值传递 原始数据类型的赋值,也是新开辟一片内存地址来存放新的指针和值,比如:var b = a;
虽然看起来b和a一样,但实际上b和a一点点关系都没有,各自有各自的标识符和占用的内存,只是刚好值相同。
引用数据类型
Object
这里的Object不是狭义的Object,包含JavaScript的预定义引用类型:Object、Array、Date、Boolean、Number、String
,对,这些都是引用数据类型。也就是一个数字/日期/布尔值/字符串他们的字面量声明方式和构造函数声明方式会造成完全不一样的结果。也就是上面划的两个重点,这里需要重新划一下。
var a = 1;
var a1 = a;
var b = {value: 1};
var b1 = b;
var c = new Object(1);
var c1 = c;
var d = new Number(1);
var d1 = d;
栈 堆
a 1 无
a1 1(和a的1占用的不同的内存) 无
b 指针,{value: 1}所占的内存地址 {value: 1}
b1 指针,指向和b相同,但指针本身存储在新的内存中 同上,且是同一块内存中的相同的值
c 指针,1所占的内存地址 1(object)
c1 指针,1所占的内存地址,但指针本身存储在新的内存中 同上,且是同一块内存中的相同的值
d 指针,1所占的内存地址 1(number)
d1 指针,1所占的内存地址,但指针本身存储在新的内存中 同上,且是同一块内存中的相同的值
简单讲,原始数据类型,永远是一个标识符对应一个值(一段内存)且都存放在栈里;引用数据类型永远是一个标识符对应一个指针指向同一个值(同一段内存),前二者存储在栈中,最后一个在堆中。来几个例子帮助理解下:
var a = 1;
var a1 = a;
a1 = 2;
console.log(a, a1); //1 2
这个很好理解大家各自有各自的标识符和内存地址,你变你的,不影响我。下一个例子:
var b = {value: 1};
var b1 = b;
b1.value = 2;
console.log(b.value, b1.value) //2 2
也好理解,b和b1指向的是同一个东西,简单理解就是b和b1共用同一个东西。b1改完了b再来访问,拿到的肯定是改后的。下一个例子:
var c = new Object(1);
var c1 = c;
c1 = 2;
console.log(c, c1) //{[[PrimitiveValue]]: 1} 2 PrimitiveValue就是指的原始值,这里其实只是将原始值1包装成Object,而这个原始值1依然不可更改
也很简单,c1 = 2;这句话重新声明了c1,代表着指针的c1被回收了,c1被重新声明为一个原始数据类型,这时候二者没关系了,如果是换一个方法,比如:
var c = new Object(1);
var c1 = c;
c1.value = 1;
console.log(c, c1) //{value: 1,[[PrimitiveValue]]: 1} {value: 1,[[PrimitiveValue]]: 1}
这样就没问题了。
参数中的原始数据和引用数据
原始数据类型是按值传递的,引用数据类型是按引用传递的,看例子:
var a = 1;
var b = {value: 1};
function foo(v){
v = "new Value";
}
foo(a);
在函数调用时,其实进行了如下操作:
将a赋值给v,也就是v = a;
,创建了a的副本,此时v得到了自己的内存,其中存放着1这个值,然后拿"new Value"去覆盖1,然而这一切发生在a的副本上,和a完全没有关系,所以此时打印出a,还是1。接着:
foo(b);
这个结果也很好猜,b也没有变,同样创建一个副本,副本有标识符、指针,指针指向的也是b的指针指向的值,但是v = ”new Value“;
执行时,这个副本就被重新赋值位一个string了,原先那个指针被回收。接着:
var a = 1;
var b = {value: 1};
var c = new Number(1);
function foo(v){
v.value = "new Value";
}
foo(a);
foo(b);
foo(c);
a依然是1,且不说原始数据不能被添加属性,即便被添加也只是a的副本的事,和a没一点关系;
b在函数执行中同样创建了副本,副本同样有指针,指向了{value: 1}
所在的实际地址,此时通过指针改变了存储`{value:
1}`的内存中的value值,所以此时再通过b去访问,一样是输出改变后的值;
c和b原理一样,只不过c本来没有value属性,所以会被添加一个value属性,所以上面的abc结果分别是:
console.log(a); // 1
console.log(b); // {value: "new Value"}
console.log(c); // Number {value: "new Value", [[PrimitiveValue]]: 1}
我们今天的关于Javascript基础教程之数据类型 和字符串 String的分享已经告一段落,感谢您的关注,如果您想了解更多关于JavaScript — 数据类型之 String字符串、Javascript——字符串数据类型(String)、JavaScript基础(一) 数据类型、JavaScript基础之数据类型的相关信息,请在本站查询。