JavaScript几个坑

坑之作用域

JavaScript的函数定义先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部,所以下面的程序并不会报错,而是会弹出 Hello, undefinded 变量 b 成了undefinded
(如果是Python一定会报local variable … referenced before assignment,因为变量未赋值前就引用了)

'use strict';

function run(){
    var a = 'Hello, ';
    alert(a+b);
    var b = 'Bob';
}

alert(run());

所以,最好严格遵守一些规范,首先申明好所有要用变量:

function factorial(){
    var 
        a = 1,
        t;   // undefinded
    for (t=1; t<=10; t++){
        a = a*t; 
    }
    return a;
}

JavaScript 在ES6中引入关键字 let 可让 for 语句中的变量申明为局部变量。

function count(){
    var 
        a = 0,
        b;
    for (let x=1; x<=10; x++){
        a += x;
    }
    b = x;  // SyntaxError
}

关键字const 可定义常量,常量名一般大写。


坑之对象

在JS中,对象类似与Python的字典, this 关键字类似于Python中的 self,在对象中定义的函数叫做方法。

var Bird = {
    name: 'pre-definded',
    age: 2,
    run: function (name){
        if (arguments.length === 1){
            this.name = name;
            }
        return ('My name is: ' + this.name);
    }
};

console.log(Bird.run('Bob'));  // 正常

如果把方法放到对象外面:

function getRun(name){
        if (arguments.length === 1){
            this.name = name;
            }
        return ('My name is: ' + this.name);
    }

var Bird = {
    name: 'pre-definded',
    age: 2,
    run: getRun
};

console.log(Bird.run('Bob')); // 正常
console.log(getRun('Bob'));  // NaN

// 但如果这么写 
var fn = Bird.run;  // 其实拿到的是getRun函数
fn(); // NaN

这是个设计缺陷,所以ECMA规定在 'use strict'this 指向undefinded, 但并没有修正这个错误:

'use strict';

var Bird = {
    name: 'pre-definded',
    age: 2,
    run: function (name){
        if (arguments.length === 1){
            this.name = name;
            }
        return ('My name is: ' + this.name);
    }
};
var f = Bird.run;
f();  // Uncaught TypeError: Cannot read property 'birth' of undefined


标准对象和包装对象

null [] {} 的类型都是 object 因此它们之间无法用typeof来区分。

typeof 123;  //"number"
typeof 123.2;  //"number"
typeof NaN; // "number"
typeof 'str';  //"string"
typeof true; //"boolean"
typeof [];  //"object"
typeof {};  // "object"
typeof null; //"object"
typeof undefined;  //"undefined"
typeof Math.abs;  //"function"



使用new创建包装对象

typeof new String('123');   // object
new String('123')  === '123';  //false

可以看出如果加了关键字 new 创造出来的对象类型为 object
如果没有关键字 new 呢?

typeof Number('123');  //Number
Number('123')  === 123;  //true

Number('123')相当于parseInt('123') 或者parseFloat('123')



使用方法toSting()转换为String类型:(null和undefined没有toString()方法)

'123'.toString(); //会报错
'123'..toString();  // 123
('123').toString();  //123


构造函数

原型链

下面创建一个数组:

var arr = [1, 2, 3];

这个数组对象的原型链为:

arr --> Array.prototype --> Object.prototype --> null

所以如果在当前对象上找不到属性时,会去 Array.prototype 上查找,再找不到去 Object.prototype上找,最后找不到,返回undefined。

普通函数的原型链为:

f --> Function.prototype --> Object.prototype --> null

由于Function.prototype定义了apply()等方法,因此,所有函数都可以调用apply()方法

function f(){
    alert('alert')
}



对象的创建方法 :

var person = {
    name: 'bob',
    say: function (){
     return ("I'm " + this.name );
     }
}



构造函数来创建对象:

function Bird(name){
    this.name = name || 'unnamed';
    this.say = function(){
        return ('Hello '+this.name);
    }
}

var bob = new Bird('Bob');
var lusi = new Bird('Lusi');
bob.name;  // 'Bob'
lusi.name;  // 'Lusi'

this指向新创建的对象,如果没有new来创建,那它就是一个普通的函数,返回undefined,其原型链为:

bob ↘
    --> Bird.prototype --> Object.prototype --> null
lusi ↗

对象的方法是不共享的:

bob.say === lusi.say; //false

要让创建的对象共享同一个函数,根据对象的属性查找原则,我们只要把函数移动到对象共同的原型上就可以了,也就是Bird.prototype:

Bird.prototype.say = function (){
    return ('Hello '+this.name);
};




参考:廖雪峰JavaScript教程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值