**
1.parseInt
**
二进制里面没有3,所以第一个NaN
2.系统的NaN原理
function myIsNaN (num){
var ret =Number(num);
ret += ""; //将ret转化为字符串
if (ret == "NaN"){
return true
}else {
return false
}
}
console.log(myIsNaN("123"))
3.引用值对比
引用值对比的是地址值
4. this指向问题
1.函数预编译过程中----------------- this ----------- window
2.全局作用域里 -----------------------t his ------------window
3.call / apply ---------------------------this ------------改变函数运行时候的this指向
4.obj.function()-------------------------this ------------function()里面的this指向obj(谁调用该方法,该方法里的this就指向谁)
eg:
var obj = {
a : function(){
console.log(this.name)
},
name : 'abc'
}
obj.a() //abc,若不调用,this指向window
eg:
var name = "222";
var a = {
name : "111",
say : function(){
console.log(this.name);
}
}
var fun = a.say;
fun() //222 fun是定义在全局的,fun()调用的this,所以this指向全局
a.say() //111 this 指向a
var b = {
name : "333",
say : function (fun){
fun ();
}
}
b.say(a.say); //222,b里面没有this,执行的是fun的this,fun定义在全局
b.say = a.say; //333
b.say();
eg:
var foo = '123';
function print (){
var foo = '456';
this.foo = '789';
console.log(foo);
}
print(); //'456'
console.log(foo) //'789'
// this指向的全局,改变了全局的foo
eg:
var foo = 123;
function print(){
this.foo = 234;
console.log(foo);
}
print() //234 先在function内部找foo,找不到后到全局中找
console.log(foo) //234 无人调用print,所以function内部的this指向全局,改变了全局的foo
eg:含有new关键字
var foo = 123;
function print(){
this.foo = 234;
console.log(foo);
}
new print(); // 123 等同于 var foo = obj.creat(print.prototype)
// 123 new关键字还没学习
console.log(foo)
eg:含有new关键字
var a = 5;
function test(){
a = 0;
alert(a);
alert(this.a);
alert(a);
}
test(); //0 5 0
new test(); //0 undefined 0
5. arguments.callee 与 caller
// argument.callee 表示函数的引用了,即函数自身
var num = (function (n){
if (n == 1){
return 1
}
return n * arguments.callee(n - 1);
}(100))
//caller 在哪儿被调用
function test(){
demo();
}
function demo(){
console.log(demo.caller)
}
test()
//ƒ test(){
demo();
}
6,var与function
function print(){
console.log(foo);
var foo = 2; //var优先级没有提升,正常的预编译环节
console.log(foo);
console.log(hello);
}
print();
// undefined 2 hello is not defined
function print(){
var test ;
test ();
function test (){
console.log(1);
}
}
print() //1
//函数声明和变量声明相同时候,函数声明优先级高
7,简单克隆与深度克隆
***(引用值的克隆与绝对值的克隆)
简单克隆
function clone (origin, target){
var target = target || {};
for (var prop in origin){
target [prop] = origin [prop];
}
return target;
}
var obj = {
name:'abc',
age:123,
sex:'female',
card:['visa','unionpay']
}
var obj1 = {};
clone(obj , obj1)
简单克隆弊端:把引用值的地址直接复制后,修改任意一个引用值都会导致两者均发生改变
深度克隆步骤:
遍历对象:for( var prop in obj)
(1)判断是不是原始值-------------------------typeof() /Object
(2)判断是数组还是对象----------------------toString() /instanceOf() /contructor—详细的见9.14
(3)建立响应的数组或者对象----------------递归
function deepClone (origin, target){
var target = target || {}, //如果target 自身原来有内容的话,自身内容也会保留下来的
toStr = Object.prototype.toString,
arrStr = "[object Array]"; //数组
if (toStr.call(origin[prop]) == arrStr){ //因为数组是对象,但是对象不是数组,所以可以通过是否是数组进行判断
target[prop] = []; //数组
}else{
target[prop] = {}; //对象
}
// 这是通过Object.prototype.toString 判断数组和对象的,和克隆关系不大
for (var prop in origin){
if (origin.hasOwnProperty(prop)){ //判断是不是私有属性
if (typeof origin [prop] == 'object'){ //判断是不是对象(数组或者对象,null先不考虑)即判断是引用值还是原始值
deepClone(origin[prop] , target[prop]);
}else{
target[prop] = origin[prop];
}
}
}
return target;
}
var obj1 = {
name : 'asd',
age : 12,
sex : 'female',
card : ['visa' , 'union']
}
var obj2 = {
height : 322
};
deepClone(obj1, obj2)
console.log(obj2)
判断数组和对象更简洁的代码:
var origin = [];
var target0 = Object.prototype.toString.call(origin),
target1 = Object.prototype.toString.call(origin) == '[object Array]',
target2 = Object.prototype.toString.call(origin) == '[object Array]' ? [] : {}
console.log(target0)
console.log(target1)
console.log(target2)
另外typeof null 的结果也是 object,所以可进一步进行区分origin的值,在克隆之前。