1. 关于链式调用
var sched = {
wakeup: function () {
console.log('Running');
return this;
},
morning: function () {
console.log('Going shopping');
return this;
},
noon: function () {
console.log('Having a rest');
return this;
},
afternoon: function () {
console.log('Studying');
return this;
},
evening: function () {
console.log('Walking');
return this;
},
night: function () {
console.log('Sleeping');
return this;
}
}
// 实现链式调用的关键是每次函数调用后返回this,jquery里面的链式调用原理也是如此
sched.wakeup().morning().noon().afternoon().evening().night();
2. 如何访问对象的属性
var myLang = {
No1: 'HTML',
No2: 'CSS',
No3: 'JavaScript',
myStudyingLang: function (num) {
console.log(this['No' + num]);//直接拼接 this.No + num 会报错
}
}
myLang.myStudyingLang(1); // 返回'HTML'
//例如
obj = {
name: '潘小姐'
}
console.log(obj['name'])
//访问obj.name的时候,js引擎在内部做了隐式转换 obj['name']
3. 对象枚举,一组有共同特性的数据集合叫枚举。
遍历,一组信息内,按顺序的一个一个获取其信息的过程叫做遍历的过程,有枚举就一定有遍历。
var car = {
brand: 'banz',
color: 'red',
displacement: '3.0'
}
for(var key in car){
console.log(car.key);//返回三个undefined,原因是因为系统内置隐式转换成了car['key'],但是系统 找不到这个值,所以返回undefined
console.log(car[key]);//可以打印
}
for in 既可以遍历对象,也可以遍历数组,区别也不大。
用for in遍历实例化出来的对象,可以打印出自定义的包括原型链上的值和属性。
function Car() {
this.brand = 'Benz';
this.color = 'red';
this.displacement = '3.0';
}
Car.prototype = {
lang: 5,
width: 2.5
}
Object.prototype.name = 'Object';
var car = new Car();
for (var key in car) {
if(car.hasOwnProperty(key)) {
console.log('自身属性' + key + ':' + car[key]);//brand, color, displacement
} else {
console.log('原型链上的属性' + key + ':' + car[key]);//lang, width, name
}
}
//hasOwnProperty,返回布尔值,只找对象自身的属性,排除掉包括原型上的不是自己的属性。
var newCar = {
color: 'red',
brand: 'banz'
}
console.log('displacement' in newCar); 返回false 系统内置隐式的做了转换 newCar['displacement'] ,不打双引号会报错
function Car2(){
this.color = 'red';
this.brand = 'banz';
}
Car2.prototype.displacement = '3.0';
var car2 = new Car2();
console.log('displacement' in car2);//true, 判断这个属性在不在 后面的值上,不排除原型
4. instanceof 判断这个对象是不是该构造函数实例化出来的(A对象的原型里到底有没有B构造函数的原型)
function Tree(){}
var tree = new Tree();
console.log(tree instanceof Tree);//true
console.log(tree instanceof Object);//true
console.log([] instanceof Object);//true
console.log([] instanceof Array);//true
console.log({} instanceof Object);//true
var a = [];
console.log(a.constructor); //Array
console.log(a instanceof Array);//true
5. 经验
var str = Object.prototype.toString.call(a);
console.log([1, 2, 3].toString());//1,2,3
console.log(str);//[object Array]
// Object.prototype = {
// toString:function(){
// this.toString();
// }
// }
//实际上就是函数里面的this替换成了a
判断是不是数组,常用的方法 ⬇
var str1 = Object.prototype.toString.call(a);
if(str1 === '[object Array]'){
console.log('是数组');
}else{
console.log('不是数组');
}
6. 关于this
function test(b){
this.d = 4;
var a = 1;
function c(){}
}
test(123);
console.log(this.d);//4
console.log(window.d);//4
console.log(d);//4
// AO = {
// arguments: [1, 2, 3],
// this: window,
// b: 123,
// a: undefined -> 1,
// c: function(){}
// }
//在普通函数内部,只要没有实例化这个函数,这个函数的this是默认指向的window.
构造函数的this指向
function Test(){
//var this = {
// __proto__: Test.prototype
//}
this.name = '123';
}
var test = new Test();
//预编译的时候,AO指向window,当new Test()的时候就执行了,GO里面产生了Test和test,且当new的时候Test内部var 了this,AO内部的this就被覆盖了,形成了原型链,this就指向了实例化的对象,test在全局
// AO = {
// this: window --> this:{name: 123, __proto__: Test.prototype}
// }
// Go = {
// Test: function(){},
// test: {
// name: 123,
// __proto__: Test.prototype
// }
// }
7. call/apply
function Person(){
this.name = '张三';
this.age = 18
}
function Programmer(){
Person.apply(this);
this.work = 'teacher';
}
var p = new Programmer();
console.log(p);//Programmer {name: '张三', age: 18, work: 'teacher'}
//apply把实例化出来的对象里的this将Person里面的this替换了
1.全局的this指向window
2.预编译阶段函数的this也指向window
3.call/apply改变this指向
4.构造函数的this指向实例化的对象
8.callee
function test02(a, b, c){
console.log(arguments.callee);//arguments.callee返回的是正在被执行的函数对象,当执行到这一 句的时候,arguments所指向的函数是谁,就返回谁
console.log(test02.length);//打印该函数形参的长度
console.log(arguments.length);//打印实参的长度
}
test02();
function test_01(){
console.log(arguments.callee);
function test_02(){
console.log(arguments.callee);
}
test_02();
}
test_01();
//打印的都是两个函数的引用
9. 用递归的方式做第n位的累加
function addSum(n){
if(n <= 1){
return 1;
}
return n + addSum(n - 1);
}
console.log(addSum(10));
//当上面的函数写成了立即执行函数,无法直接写函数名,就可以用上arguments.callee找到这个函数
var res = (function(n){
if(n <= 1){
return 1;
}
return n + arguments.callee(n - 1);
})(10);
console.log(res);//55
10. caller 打印调用当前函数的函数引用,谁当前调用了这个函数,就返回哪个函数(严格模式下会报错),在被调用的函数打印这个函数的caller,就可以打印出谁调用了它
test_03();
function test_03(){
test_04();
}
function test_04(){
console.log(test_04.caller);//打印出来是test_03()整个函数
}
笔试/面试题 部分
1. 壹
function foo(){
bar.apply(null, arguments)
}
function bar(){
console.log(arguments);
}
foo(1, 2, 3, 4, 5)
//结果打印1, 2, 3, 4, 5.事实上,每个函数的执行都相当于 函数名.call(),现在是bar.apply(),apply的第一个值又是null,this指向并没有更改,arguments传的值是数组,而 bar的参数又是空的,也就是相当于给bar传值并且执行,所以是1, 2, 3, 4, 5
2. JS的typeof能返回的值有哪些, string,number,boolean,undefined,object,function
3. 叁
function b(x, y, a){
arguments[2] = 10;
console.log(a);//10
}
b(1, 2, 3);
//实参与形参是相互映射的关系,你改我也改,我改你也改
4. 肆
var f = (
function f(){
return '1';
},
function g(){
return 2;
}
)
console.log(typeof f);//function,逗号运算符,所以肯定返回最后面的函数 ,函数typeof出来返回 function
var f = (
function f(){
return '1';
},
function g(){
return 2;
}
)();
console.log(typeof f);//number,逗号运算符,所以肯定返回最后面的函数,又有括号,成为了表达式相当于f() ,typeof(2)出来返回number
5. 伍
console.log(undefined == null);//true
console.log(undefined === null);//fales
console.log(isNaN(100));//fales
console.log(parseInt('1a') == 1);//true,parseInt从头开始找,直到出现非数为止,再隐式类型转换成number,最后再parseInt
function isNaN1(num){
var res = Number(num) + '';
if(res == 'NaN'){
return true;
}else{
return false;
}
}
console.log(isNaN1('123'));//false NaN不等于任何数,包括自己
6. { } == { } 等不等于?为什么不等于?怎样让它等于?
因为引用值对比的是地址
var obj = { };
obj1 = obj;
这个时候就相等
7. 柒
var a = '1';
function test_05(){
var a = '2';
this.a = '3';
console.log(a);
}
test_05();//打印的var a = '2';
new test_05();//打印的是a,不是this.a,所以还是2
console.log(a);//打印this.a = '3';
8. 捌
var n = 5;
function test_06(){
n = 0;
console.log(n);
console.log(this.n);
var n;
console.log(n);
}
test_06();//第一个console.log是0,第二个this.n是找外面的n所以是5,第三个还是0
new test_06();//第一个console.log找自己,有肯定打印自己所以是0,实例化确实存在this,但是没有this.n这个属性,所以undefined,第三个还是0
//结果返回0, 5, 0, 0, undefined, 0
作业部分
1. 写一辆车的构造函数,再写一个人的构造函数,用apply借用车的属性
function Car(brand, color, displacement){
this.brand = brand;
this.color = color;
this.displacement = displacement; //排量
this.info = function(){
return '排量为' + this.displacement.toFixed(1) + '的' + this.color + this.brand;
}
}
function Person(opt){
Car.apply(this, [opt.brand, opt.color, opt.displacement]);
this.name = opt.name;
this.age = opt.age;
this.say = function(){
console.log('年龄为'+ this.age + '的' + this.name + '买了一辆' + this.info());
}
}
var p = new Person({
color: '红色',
displacement: 3.0,
brand: 'banz',
name: '潘小姐',
age: 18
})
p.say();