JavaScript 搜罗的问题

1.使用 With 关键字延长作用域链 

var test = {
    name :'name'
}
with(test){
    console.log(name);//?
}

问题: 这段代码的结果是什么? 


2. JavaScript的参数传递为值传递

function setName(obj){
    obj.name = "Nicholas";
    obj = new Object();
    obj.name = "Greg";
}
var person = new Object();
setName(person);
console.log(person.name);//?

问题: 这段代码的结果是什么


3. 变量类型使用 typeof 判断, 是否是某个对象的实例使用 instanceof 判断

例子:

var str1 = "str";
console.log(typeof str1);//String
var str2 = ["str1", "str2"];
console.log(str2 instanceof Array);//true


4. 使用 var 声明的变量会被添加到最近的环境中, 没有使用 var 声明的变量会被添加到全局环境中

实例1.

function add(num1, num2){
    var sum = num1 + num2;
}
add(10, 20)
console.log(sum);//结果: sum is not defined
function add(num1, num2){
    sum = num1 + num2;
}
add(10, 20)
console.log(sum);//结果: sum = 30


5. JavaScript 数组的 length 属性不是只读的, 可以修改数组的属性,删除数组元素等

例子:

var array = ["name1", "name2", "name3"];
array.length = 2;
console.log(array);//输出 [ "name1", "name2" ]


6. JavaScript 中可以使用unshift(),shift()向数组头部插入, 取出值;使用push(),pop() 向数组尾部插入,取出值;

tips: 数组还可以做为 栈 或者 队列去使用

例子1: push() + pop() 作为栈使用

var array = [];
array.push("name1");
array.push("name2");
array.pop();
console.log(array.toString());//输出 name1

例子2: push() + shift() 作为队列使用

var array = [];
array.push("name1");
array.push("name2");
array.shift();
console.log(array.toString());//输出 name2

7. Array.sort() 将将所有的数据项调用 toString() 方法后,按照字符串的值进行排序

var array = [1, 2, 11];
console.log(array.sort());//输出值: [1, 11, 2]

tips: 如何使使数组排序结束后序列为:[1, 2, 11]呢? 

方案: 定义比较函数compare, 调用sort(compare)使用自定义规则排序


8. concat(), slice, splice() 函数的使用

concat: 合并多个数组,并返回新的数组对象

slice: 获取当前数组的子集

splice() 的使用案例

var array = [1, 2, 3];
array.splice(0, 0, "4");//添加元素
console.log(array);//["4", 1, 2, 3]
array.splice(0, 1, "5");//替换元素
console.log(array)//["5", 1, 2, 3]
array.splice(0, 1);//删除元素
console.log(array);//[1, 2, 3]


9.数组迭代的方法: every(), filter(), forEach(), map(), some();(tips: 迭代方法不改变原来的数组元素)

  1. every(). 所有的结果返回布尔值,函数返回值为[所有结果的交集]

  2. some(). 所有的结果返回布尔值,函数返回值为 [所有结果的并集]

  3. filter().  所有的结果返回布尔值,函数返回值为 [所有返回值为 true 的元素对象]

  4. forEach(). 对所有的元素执行相同的函数,没有返回值; 本质上等同于 for 循环 

  5. map().     对所有的元素执行相同的函数,返回值为[每个新元素组成的新数组]

//1. every() 函数,判断所有的元素是否都大于2
var array = [1, 2, 3, 2, 1];
var result = array.every(function(item, index){
    return item > 2;
});
console.log(result);//返回值为false

//2. some() 函数,判断集合中是否有大于2的元素
var array = [1, 2, 3, 2, 1];
var result = array.some(function(item, index){
    return item > 2;
});
console.log(result);//返回值为true

//3. filter() 函数, 返回集合中大于2的所有元素
var array = [1, 2, 3, 2, 1];
var result = array.filter(function(item, index){
    return item > 2;
});
console.log(result);//返回值为:[3]

//4. forEach() 等价于 for 循环

//5. map()函数,将所有的元素的值变为原来值的平方
var array = [1, 2, 3, 2, 1];
var result = array.map(function(item, index, array){
    return item*item;
});
console.log(result)//返回值: [1, 4, 9, 4, 1]


10.正则对象: RegExp

    test(str), 返回布尔值,判断字符串是否匹配

    exec(str), 返回匹配的字符串


11. 函数定义的三种方式:

//1. 使用函数声明方式
function sum(num1, num2){
    return num1 + num2;
}

//2. 使用函数表达式
var sum = function(num1, num2){
    return num1 + num2;
}

//3. 使用函数的构造函数
var sum = new Function("num1", "num2", "return num1 + num2");


12. 函数声明提升.  在代码开始执行之前,解析器就已经通过一个名为函数声明提升的过程,读取并将函数声明添加到执行环境中。对代码求值时,JavaScript 引擎在第一遍会声明函数并将他们放到源代码的顶部(即使声明函数的代码在return的后面)

tips: 函数表达式(匿名函数)不会被提升

//函数声明被提升
console.log(sum(10, 10));//20
function sum(num1, num2){
    return num1 + num2;
}
//函数表达式不会被提升
console.log(sum(10, 10));//sum is not defined
var sum = function(num1, num2){
    return num1 + num2;
}


13.函数内部获取函数体

var sum = function(num1, num2){
    console.log(arguments.callee);//输出 function(...){ ... }
}
sum(1,2);

用处:用于递归等函数中,避免了函数执行与函数名的耦合

案例:函数递归

function factorial(num){
    if(num <= 1){
        return 1;
    }else{
	return num * arguments.callee(num - 1);
    }
}
console.log(factorial(5));//120


14. JavaScript 中有两种属性类型: 1.数据属性   2.访问器属性

数据属性有四个特性:  

        1) Configurable, 属性是否可以被删除

        2)  Enumerable,  属性能否被 for-in 循环去访问

        3) Writable, 属性的数据值是否只读

        4) Value, 属性的数据值           

//定义一个有 name 属性的对象,该属性的值为Nicon,且该值只读
var obj = {};
Object.defineProperty(obj, "name", {
    writable: false,
    value: "Nicon"
});
obj.name = "changed";
console.log(obj.name);//输出为 Nicon

访问器属性有四个特性:

        1) Configurable, 属性不可删除

        2)Enumerable,属性不能被 for-in  循环访问   

        3) set, 定义变量的赋值方法

        4) get, 定义变量的访问方法


15. prototype: 通过构造函数而创建的那个对象实例的原型对象,每个函数都有内部的prototype 属性.

每当代码读取某个对象的属性时,都会执行一次搜索,目标是具有给定对象名字的属性。搜索首先从对象实例本身开始。如果在实例中找到了具有给定属性的名字,则返回该属性的值;如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性,则返回该属性。

//name 属性在对象实例上找到,不再查找prototype
function Person(){
    this.name = "Nichol";   
}
Person.prototype.name = "Not Nichol";
console.log(new Person().name);//输出 Nichol
console.log(new Person().hasOwnProperty("name"))//输出true,拥有实例属性:name
//name 属性在对象实例上查找不到,搜索prototype
function Person(){
}
Person.prototype.name = "Not Nichol";
console.log(new Person().name);//输出 Not Nichol
console.log(new Person().hasOwnProperty("name"))//输出false, 没有实例属性:name


16. in 在 对象属性中的应用

    1) 对象的实例对象或者原型对象中,包含属性,返回true

function Person(){
}
Person.prototype.name = "Not Nichol";
console.log("name" in Person)//返回true

   2)  进阶: 通过 in 和 hasOwnProperty 判断对象是否有原型属性

Object.prototype.hasPrototypeProperty = function(property){
    return !this.hasOwnProperty(property) && (property in this)
}
function Person(){}
Person.prototype.name = "Not Nichol";
var person = new Person();
console.log(person.hasPrototypeProperty("name"));//返回 true

    3) 使用 for-in 循环获取对象的属性(此写法等价于 Object.keys(Person) )

var Person = {
    name: 'name',
    age: 'age'
}
for(var property in Person){
    console.log(property);//输出 name, age
}


17. 继承。 JavaScript 通过原型链实现了继承.(原型链本质上是拓展了原型搜索机制)

小问题: 为什么所有的自定义类型都有 toString(), valueOf() 方法

原因: 所有自定义类型的prototype 指向了 Object.prototype

function SuperType(){//父类构造函数
    this.property = true;
}
SuperType.prototype.getSuperValue = function(){//父类原型函数
    return this.property;
}
	
function SubType(){//子类构造函数
    this.property = false;
}
SubType.prototype = new SuperType();//通过子类的原型对象引用父类的实例对象, 实现原型链传递
var instance = new SubType();
console.log(instance.getSuperValue());//返回false


18: 闭包: 是指有权访问另一个函数作用域中的变量的函数

首先:闭包必须是一个函数

然后:该函数能够访问另一个函数作用域中的变量


19: 匿名函数的执行环境具有全局性(比如下面这个)

var name = "window";
var obj = {
    name: 'obj',
    getName: function(){
        return function(){
            return this.name;
        }
    }
}
console.log(obj.getName()());//输出window

如何避免,匿名函数执行时返回结果,与预期不一致

//通过在匿名函数中使用其他变量替换 this 实现
var name = "window";
var obj = {
    name: 'obj',
    getName: function(){
        var that = this;
        return function(){
            return that.name;
        }
    }
}
console.log(obj.getName()());//输出obj


20. 定义块级作用域

使用这种方式的原因: 限制向全局作用域中添加过多的变量和函数

(function(){
    //块级作用域
})()



小技巧集锦:

//1. 获取 global 对象
var global = function(){
    return this;
}
//2. apply() 和 call() 的使用
var arr = [1, 4, 2];
console.log(Math.max.apply(this, arr))//函数参数使用数组传入
console.log(Math.max.call(this, 1, 4, 2));//函数参数按照参数1,参数2一个个输入



转载于:https://my.oschina.net/u/2308424/blog/632972

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值