72.类数组:属性要为索引(数字)属性,必须有length(类数组关键点)属性,最好加上push
1.是对象,可以当作数组来用,把数组和对象拼接到一起,但并不是所有的方法都能用的,有的需要自己填。
例1:
var obj = {
"0" : 'a',
"1" : 'b',
"2" : 'c',
"length" :3,
"push" : Array.prototype.push,
"splice" : Array.prototype.splice,
}
例2:
var obj = {
"2" : 'a',
"3" : 'b',
"length" :2,
"push" : Array.prototype.push,
}
obj.push('c');
obj.push('d');
/* Array.prototype.push = function (target){
obj[obj.length] = target;
obj.length ++;
}*/
返回结果:{2: "c", 3: "d", length: 4}
例3:
var obj = {
"0" : 'a',
"1" : 'b',
"2" : 'c',
name : 'L',
age : 21,
length : 3,
push : Array.prototype.push,
splice : Array.prototype.splice,
}
obj.length 返回 3
obj.name 返回 "L"
for(var prop in obj){ console.log(obj[prop])} 返回 obj全部属性值
例4:封装type
大致思路:
先判断 原始值引用值
原始值:再分为null和其他,null单独判断,其他利用typeof判断再返回类型就行
引用值:函数直接返回就行,再判断对象,数组,和包装类对象等利用Object.prototype.toString.call();
function type (target){
var template = {
"[object Array]" : "array",
"[object Object]" : "object",
"[object Number]" : "number - object",
"[object Boolean]" : "boolean - object",
"[object String]" : "string - object",
}
if(target === null){
return "null";
}
else if(typeof(target) == "object"){
var str = Object.prototype.toString .call(target);
return template[str];
}
else {
return typeof(target);
}
}
简化:
var ret = typeof(target); 然后把所有的 typeof(target)换成ret就行,只需判断一次就行
例5重要:数组去重
大致思路:将数组的属性值作为对象的属性名,将对象属性值赋一个非false的数,然后进行循环。
var arr = [1,1,1,1,1,2,2,2,2,2,1,1,1,1,0,0,0,0,0];
/* var temp = {
"1" : "abc",
"2" : "abc",
}
temp[1] --> undefined
temp[1] --> "abc"
temp[2] --> undefined
*/
Array.prototype.unique = function (target){
var temp = {}
arr = [];
len = this.length;
for(var i = 0 ;i < len; i++){
if(!temp[this[i]]){
temp[this[i]] = "abc";
arr.push(this[i]);
}
}
return arr;
}
如果:将"abc"改成"this[i]"就达不到0去重的效果了,因为temp[this[i]] 结果为0 ,那么取非是true,在判断条件哪里,0可以一直执行,所以错了。
var arr = [1,1,1,1,1,2,2,2,2,2,1,1,1,1,0,0,0,0,0];
Array.prototype.unique = function (target){
var temp = {}
arr = [];
len = this.length;
for(var i = 0 ;i < len; i++){
if(!temp[this[i]]){
temp[this[i]] = this[i];
arr.push(this[i]);
}
}
return arr;
}
第13节数组去重,习题,答疑复习
原始值与引用值两大区别:
1.存储地址不一样
2.原始值没有属性和方法
引出问题1:
var str = "abc"
console.log(str.length);
内部转化原因:
会在内部生成字符串对象new String('abc')
然后执行时执行的其实是new String('abc').length
以上隐式包装的过程就称为包装类。
引出问题2:
var number = 123;
num.abc = "abc";
console.log(num.abc);
内部转化:
会在内部生成new Number(num).abc = 'abc'; --> delete
然后再下一步访问是因为你上一个已经销毁了,然而这里有要调用,所以系统又构造出了一个new Number(num).abc 这个里面什么也没存,所以返回undefined
不可配置的属性:一旦经历了var的操作,所得出的属性,window,这种属性叫做不可配置的属性不可配置的属性,delete不掉
不可配置的属性: var num = 123; delete num --> flase
可配置的属性: obj.num = 123; delete num --> true
Object.create(prototype,definedProperty) (了解)
this:
1.预编译 this --> window
2.谁调用 this 指向谁
3.call apply
4.全局 this --> window
例1:
function test(){
var num = 123;
function a(){
}
}
test(); < == > test.call()
//test执行就会生成以下内容
-- >AO{
arguments.{},
this : window,
num : undefined,
a : function (){}
}
例2:
function test(){
console.log(this);
}
test.call({name : "deng"});
//test.call({name : "deng"});执行就会生成以下内容
-- >AO{
arguments.{},
this : {name :"deng"},
num : undefined,
a : function (){}
}
例3:
var name = 'window';
var obj = {
name : 'obj',
say : function (){
console.log(this.name);
}
}
obj.say.call(window);
//只要有call出现就打破一切规则,this就指向传进去的东西。
例4:
var name = 'window';
var obj = {
name : 'obj',
say : function (){
console.log(this.name);
}
}
var fun = obj.say;
fun();
//相当于这个函数在全局范围内自调用,相当于把say那个函数引用拿出来了
闭包:只要是将内部函数保存到了外部就一定形成闭包,不管什么方式,只要保存到了外部就必然生成闭包,不一定是return的方式
var obj = {}
function a (){
var aa= 123;
function b (){
console.log(aa);
}
obj.fun = b;
}
a();
//b被保存到了外部,并且一直拿着a的执行期上下文,死死不放手,a消失了,b还活的好好的,照样能访问a里的变量
例1:
function Person (){
// var this = {
// makeMoney : function (){}
// offer : function (){}
// }
var money = 100;
this.name = name;
this.makeMoney = function (){
money ++;
}
this.offer = function (){
money --;
}
// return this
}
var person = new Person();
//经过new之后就会在Person内部产生this,然后将this返回,连带着this对象上打包的两个方法都返回到了外部,这样,这两个方法就和Person生成的执行期上下文形成了闭包
//这样这两个方法就能操作同一个money,money保存到了Person里面并且外部不可访问,因为money在Person方法也就是makeMoney和offer的作用域链中
//money就作为Person的私有化变量来存在。
[] + "" --> ""
[] + 1 --> "1"
[] - 1 --> -1
[] == [] -- > false 因为每个引用值都有一个独特的地址
//以上都进行了隐式类型转换
深度克隆原理:
var obj = {
name : "abc",
wife : {
name : "xiaoliu",
son :{
name : "xiaodeng",
}
}
}
var obj1 = {
name : obj.name,
wife : {
name : obj.wife.name,
son : {
name : obj.wife.son.name,
}
}
}
//首先obj1 空对象
第一个属性:原始值直接赋值,
第二个属性:引用值->对象类型->新建对象
第二个属性中第一个属性:原始值直接赋值
第二个属性中第二个属性:引用值->对象类型->新建对象
依次就是深度克隆原理
undefined 和null 和0
并不是所有东西比较都会进行隐式类型转换的,尤其是大于小于号这里
系统规定:undefined和null就是不能和数 像0什么的进行比较。
例题:
(function (x){
//var x
delete x;
return x;
}(1))
//相当于var x 是删不掉的 所以返回1。
例题:
function test(){
console.log(typeof(arguments));
}
test();
//返回object
例题:
var h = function a(){
return 23;
}
console.log(typeof(a));
//报错 h才是函数名,调用h才执行
然后的例题就是另一个文档中了