目录
一、数组去重(选择排序的思路)
var arr = ['a', 'a', 'a', 'b', 'b', 'a', 'c', 'b', 'c', 'f', 'g', 'f', 'g', 's']
for(var i=0; i<arr.length-1; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i] == arr[j]){
arr.splice(j, 1)
}
}
}
这样会出现一个问题:
当有多个连续的字符的时候,在删除当前字符的时候,后面的会进行补位操作(这个时候进行补位的元素和前面被删除的元素是一样的),由于前面已经比较过了,因此程序不会回过头再进行比较一次,所以产生了'漏网之鱼'
解决方法是:让他再回来比较一次,也就是在删除之后加一个j--
var arr = ['a', 'a', 'a', 'b', 'b', 'a', 'c', 'b', 'c', 'f', 'g', 'f', 'g', 's']
for(var i=0; i<arr.length-1; i++){
for(var j=i+1; j<arr.length; j++){
// 'a' == 'a' 满足条件的,进入判断体里面
// 'a' == 'a' 满足条件的,进入判断体里面
// 'a' == 'b' 不满足条件的,因此去执行j++,j=2
if(arr[i] == arr[j]){
// 1,因此把第二个a字符给删除掉
// 1,因此把第二个a字符给删除掉
arr.splice(j, 1)
// 1--,变成了0
// 1--,变成了0
j--
}
}
}
console.log(arr) // ['a', 'b', 'c', 'f', 'g', 's']
程序的封装:
第一步:先把业务代码放进一个函数里面,再起一个语义化的名称
第二步:观察哪些数据是可以变化的,把他提成参数去使用
第三步:把结果返回给外界
二、栈区和堆区
电脑的存储空间
运行内存,当你打开一个软件的时候,软件其实是在运行在内存里面执行的
硬盘,你下载的软件或许资料都是存储在硬盘里面的,硬盘一般比较大的
内存存储问题
这里的内存是运行内存,代码执行是在运行内存里面的。包括变量的存储也是在内存里面的
栈区
主要用来存储基本数据类型的,引用数据类型的地址是存储在栈区
堆区
主要用来存储引用数据类型的
三、拷贝传值和引用传址
1.拷贝传值:将一个变量的值"拷贝"一份,传给了另一个变量,也可以说是复制
基本数据类型都是"拷贝传值"。
拷贝传值中,两个变量之间没有任何联系,修改其中一个变量的值,另一个不会改变。这两个变量之间,是相互独立的,没有任何联系。
基本数据类型存在"快速内存"(也叫栈内存)中的。因为,基本数据类型只有一个变量名和一个变量值。
var a=10;//声明变量
var b=a;//将变量a的值"拷贝"一份,赋给变量b
a=100; //重新给变量赋值100
alert(b);//10
alert(a);//100
2.引用传址:复合数据类型都是"引用传地址"
复合数据类型的存储分两步:
a、将变量名和数据地址存"快速内存"(也叫栈内存)中。
b、具体的数据存在"慢内存"(也叫堆内存)中。
引用传址:将一个变量的数据地址,"拷贝"一份,传给了另一个变量。这两个变量,指向"同一个地址"。 大家共享同一份数据。
如果其中一个变量的值发生了改变,那么,另一个变量的值也得变。要变一起变。 因此,这两个变量是有联系的,要变大家一起变。
ar arr1["张三",24,"本科"];
var arr2=arr1;//将arr1的地址,"拷贝"一份,传给了另一个变量arr2
arr[1]=30; //给变量arr[1]重新赋值30
alert(arr2[1]);//arr2[1]=30
四、对象
1.定义
{} 字面量
new Object() 构造函数
2.作用
对象类型的结构更为清晰(数据结构)
对象添加很多的属性和方法
可以避免变量命名污染问题
3.组成
由键值对组成的 key: value,键,值对分为属性和方法,因此也可以说对象是由属性和方法组成的
4.属性和方法:
属性指的是静态的东西,例如:姓名、性别
方法指的是动态的东西,例如:开飞机、开车
// 构造函数
var obj = new Object()
// 添加属性,属性和属性值之间使用等号连接
obj.name = '蔡徐坤'
obj.sex = '男'
// 添加方法,方法和值之间使用等号连接
obj.saying = function(){
console.log('基尼太美')
}
console.log(obj.name) //蔡徐坤
obj.running() //基尼太美
//字面量
var obj = {}
obj.name = '蔡徐坤'
obj.sex = '男'
obj.saying = function(){
console.log('基尼太美')
}
//利于字面量方式简化设置属性和方法的操作
// 在字面量方式的内部添加,键和值之间使用冒号隔开,逗号结尾,最后一个不需要逗号
var obj = {
name:'蔡徐坤',
sex:'男',
saying: function(){
console.log('基尼太美')
},
//方法还可以这样定义
playing(){
console.log('唱,跳,RAP,篮球')
}
}
5.不同类型的对象
object对象,在js里面对象是一个大的范畴,对象它的形态是不一样的
var arr = ['a', 'b']
var obj = {a: 1}
var btn = document.getElementById('btn')
window
document
他们都是不同形态的对象
面试题一:
var arr = ['a', 'b', 'c']
//注意点:数组是属于对象,可以使用自定义对象添加属性的方式,但是为了不破坏原有的数据结构,
//不会算在下标里面。依旧会以键值对的形式存在
arr.d = 'hello'
console.log(arr)
console.log(arr.length)
console.log(arr.d)
注意点:数组是属于对象,可以使用自定义对象添加属性的方式,但是为了不破坏原有的数据结构,不会算在下标里面。依旧会以键值对的形式存在
面试题二:
var btn = document.getElementById('btn')
console.log(btn)
btn.a = 1
console.log(btn.a)
注意点:给标记添加属性,属于隐式添加不会显示在标记上面,但是添加的属性可以使用
6.对象的赋值方式
第一种使用点的形式:对象名称.属性名称或者方法名 = 值
第二种使用[]的形式:对象名称[属性名称或者方法名] = 值 ;[]形式更灵活,因为[]可以解析变量,而点不能解析变量
注意点:添加的键对象都会默认转成字符串类型
//第一种使用点的形式
var obj = {}
obj.name = '蔡徐坤'
//第二种使用[]的形式
var obj = {}
//如果在添加键的时候,不加引号,会默认当成变量去解析。如果加了引号会当成键名去解析
obj['name'] = '蔡徐坤'
//当键名是不确定的时候,可以使用这种方法让用户去自定义
var key = '爱好'
var obj = {}
obj[key] = '唱,跳,RAP,篮球'
console.log(obj) //{爱好:'唱,跳,RAP,篮球'}
//若是写成这种形式,会直接把key当成对象的键名进行添加
obj.key = '唱,跳,RAP,篮球'
console.log(obj) //{key:'唱,跳,RAP,篮球'}
//遍历对象
var arr = ['a','b']
var obj = {
name: '张三',
age: 18,
123: '我是数值类型',
'["a", "b"]': '哈哈!我是一个数组'
[arr]: '哈哈' //会把arr通过toString()转成a,b再作为属性名称
}
//遍历属性名
for(var key in obj){
console.log(key)
}
//遍历属性值
for(var key in obj){
console.log(obj[key])
}